**《Linux/Unix系统编程手册》读书笔记24章**

D 24章 进程的创建 425
24.1 fork()、exit()、wait()以及execve()的简介 425
. 系统调用fork()允许父进程创建子进程
. 库函数exit(status)终止进程,将进程占用的所有资源归还内核,交其进行再次分配。库函数exit()位于系统调用_exit()之上。在调用fork()之后, 父,子进程中一般只有一个会通过调用exit()退出,而另一个进程则应适用_exit()终止。
在这里插入图片描述

#define _BSD_SOURCE
#include “tlpi_hdr.h”

int main(int argc, char *argv[]){
int istack = 222;

switch (vfork()) {
case -1:
    errExit("vfork");

case 0:             /* Child executes first, in parent's memory space */
    sleep(3);                   /* Even if we sleep for a while,
                                   parent still is not scheduled */
    write(STDOUT_FILENO, "Child executing\n", 16);
    istack *= 3;                /* This change will be seen by parent */
    _exit(EXIT_SUCCESS);

default:            /* Parent is blocked until child exits */
    write(STDOUT_FILENO, "Parent executing\n", 17);
    printf("istack=%d\n", istack);
    exit(EXIT_SUCCESS);
}

}
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ gcc t_vfork.c -o t_vfork error_functions.c curr_time.c
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ ./t_vfork
Child executing
Parent executing
istack=666
提示:除非速度绝对重要的场合,新程序应当舍弃vfork()而取用 fork()
. 系统调用wait(&status)目的:1. 子进程尚未调用exit()终止,那么wait()会挂起父进程直至子进程终止。2. 子进程的终止状态通过wait()的status参数返回。
. 系统调用execve(pathname, argv, envp)到当前进程的内存。

FBReader也叫E-book Viewer,可以安装在ubuntu系统中来打开mobi文件。安装方式如下,终端执行:sudo apt install fbreader
24.2 创建新进程:fork() 427
创建多个进程是任务分解行之有效的方法。例如,网络服务器进程可在侦听客户端请求的同时,为处理每一请求而创建一新的子进程,与此同时,服务器进程会继续侦听更多的客户端连接请求。好处,简化应用程序的设计,同时提高了系统的并发性。
子进程的栈,数据,以及栈段开始时是对父进程内存相应各部分完全复制。执行fork()后,每个进程均可修改各自的栈,数据,堆段中的变量。
fork()通过返回值来区分父, 子进程。fork()在子进程中返回0。
子进程调用 getpid() 获取自身的进程。
父进程调用 getppid() 获取进程。
无法创建fork()子进程,返回-1。原因:a. 进程数量要么超出了系统针对此真实用户在进程数量上所施加的限制。b. 触及允许该系统创建的最大进程这一系统级上限。
#include “curr_time.h” /* Declaration of currTime() */
#include “tlpi_hdr.h”
#include “error_functions.h”
#include “curr_time.h”

static int idata = 111; /* Allocated in data segment */
int main(int argc, char argv[]){
int istack = 222; /
Allocated in stack segment */
pid_t childPid;

switch (childPid = fork()) {
case -1:
    errExit("fork");

case 0:
    idata *= 3;
    istack *= 3;
    break;

default:
    sleep(3);                   /* Give child a chance to execute */
    break;
}
/* Both parent and child come here */
printf("PID=%ld %s idata=%d istack=%d\n", (long) getpid(),
        (childPid == 0) ? "(child) " : "(parent)", idata, istack);
exit(EXIT_SUCCESS);

}
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ gcc t_fork.c -o t_fork error_functions.c curr_time.c
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ ./t_fork
PID=4372 (child) idata=333 istack=666
PID=4371 (parent) idata=111 istack=222

		**24.2.1 父、子进程间的文件共享 428** 

#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include “tlpi_hdr.h”

int main(int argc, char *argv[]){
int fd, flags;
char template[] = “/tmp/testXXXXXX”;

setbuf(stdout, NULL);                   /* Disable buffering of stdout */

/* Open a temporary file, set its file offset to some arbitrary value,
   and change the setting of one of the open file status flags. */

fd = mkstemp(template);
if (fd == -1)
    errExit("mkstemp");

printf("File offset before fork(): %lld\n",
        (long long) lseek(fd, 0, SEEK_CUR));

flags = fcntl(fd, F_GETFL);
if (flags == -1)
    errExit("fcntl - F_GETFL");
printf("O_APPEND flag before fork() is: %s\n",
        (flags & O_APPEND) ? "on" : "off");

switch (fork()) {
case -1:
    errExit("fork");

case 0:     /* Child: change file offset and status flags */
    if (lseek(fd, 1000, SEEK_SET) == -1)
        errExit("lseek");

    flags = fcntl(fd, F_GETFL);         /* Fetch current flags */
    if (flags == -1)
        errExit("fcntl - F_GETFL");
    flags |= O_APPEND;                  /* Turn O_APPEND on */
    if (fcntl(fd, F_SETFL, flags) == -1)
        errExit("fcntl - F_SETFL");
    _exit(EXIT_SUCCESS);

default:    /* Parent: can see file changes made by child */
    if (wait(NULL) == -1)
        errExit("wait");                /* Wait for child exit */
    printf("Child has exited\n");

    printf("File offset in parent: %lld\n",
            (long long) lseek(fd, 0, SEEK_CUR));

/*
通常将存放文件偏移量的数据类型off_t实现为一个有符号的长整型,在32位体系架构中,文件大小为2GB限制,在64位体系架构中,限额远远超出目前的磁盘容量,无实际意义。_FILE_OFFSET_BITS宏,要求程序代码编写必须规范。声明用于放置文件偏移量的变量,应正确地使用off_t, 而不能使用“原生”的C语言整型。
*/
flags = fcntl(fd, F_GETFL);
if (flags == -1)
errExit(“fcntl - F_GETFL”);
printf(“O_APPEND flag in parent is: %s\n”,
(flags & O_APPEND) ? “on” : “off”);
exit(EXIT_SUCCESS);
}
}
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ gcc fork_file_sharing.c -o fork_file_sharing error_functions.c curr_time.c
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ ./fork_file_sharing
File offset before fork(): 0
O_APPEND flag before fork() is: off
Child has exited
File offset in parent: 1000
O_APPEND flag in parent is: on

		****24.2.2 fork()的内存语义 430**** 

在这里插入图片描述

	****24.3 系统调用vfork() 433** 
	**24.4 fork()之后的竞争条件(Race Condition) 434**** 

#include <sys/wait.h>
#include “tlpi_hdr.h”

int main(int argc, char *argv[]){
int numChildren, j;
pid_t childPid;

if (argc > 1 && strcmp(argv[1], "--help") == 0)
    usageErr("%s [num-children]\n", argv[0]);
numChildren = (argc > 1) ? getInt(argv[1], GN_GT_0, "num-children") : 1;

setbuf(stdout, NULL); /* Make stdout unbuffered */

for (j = 0; j < numChildren; j++) {
    switch (childPid = fork()) {
    case -1:
        errExit("fork");

    case 0:
        printf("%d child\n", j);
        _exit(EXIT_SUCCESS);

    default:
        printf("%d parent\n", j);
        wait(NULL);                 /* Wait for child to terminate */
        break;
    }
}

exit(EXIT_SUCCESS);

}
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ gcc fork_whos_on_first.c -o fork_whos_on_first error_functions.c curr_time.c get_num.c //要求只产生一个进程
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ ./fork_whos_on_first 1
0 parent
0 child

	****24.5 同步信号以规避竞争条件 436**** 

#include <signal.h>
#include “curr_time.h” /* Declaration of currTime() */
#include “tlpi_hdr.h”
#include “error_functions.h”
#include “curr_time.h”

#define SYNC_SIG SIGUSR1 /* Synchronization signal */

static void /* Signal handler - does nothing but return */
handler(int sig)
{
}

int
main(int argc, char *argv[])
{
pid_t childPid;
sigset_t blockMask, origMask, emptyMask;
struct sigaction sa;

setbuf(stdout, NULL);               /* Disable buffering of stdout */

sigemptyset(&blockMask);
sigaddset(&blockMask, SYNC_SIG);    /* Block signal */
if (sigprocmask(SIG_BLOCK, &blockMask, &origMask) == -1)
    errExit("sigprocmask");

sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = handler;
if (sigaction(SYNC_SIG, &sa, NULL) == -1)
    errExit("sigaction");

switch (childPid = fork()) {
case -1:
    errExit("fork");

case 0: /* Child */

    /* Child does some required action here... */

    printf("[%s %ld] Child started - doing some work\n",
            currTime("%T"), (long) getpid());
    sleep(2);               /* Simulate time spent doing some work */

    /* And then signals parent that it's done */

    printf("[%s %ld] Child about to signal parent\n",
            currTime("%T"), (long) getpid());
    if (kill(getppid(), SYNC_SIG) == -1)
        errExit("kill");

    /* Now child can do other things... */

    _exit(EXIT_SUCCESS);

default: /* Parent */

    /* Parent may do some work here, and then waits for child to
       complete the required action */

    printf("[%s %ld] Parent about to wait for signal\n",
            currTime("%T"), (long) getpid());
    sigemptyset(&emptyMask);
    if (sigsuspend(&emptyMask) == -1 && errno != EINTR)
        errExit("sigsuspend");
    printf("[%s %ld] Parent got signal\n", currTime("%T"), (long) getpid());

    /* If required, return signal mask to its original state */

    if (sigprocmask(SIG_SETMASK, &origMask, NULL) == -1)
        errExit("sigprocmask");

    /* Parent carries on to do other things... */

    exit(EXIT_SUCCESS);
}

}

(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ gcc fork_sig_sync.c -o fork_sig_sync error_functions.c curr_time.c
(base) wannian07@wannian07-PC:~/Desktop/std/linux prog$ ./fork_sig_sync
[15:21:36 4518] Parent about to wait for signal
[15:21:36 4519] Child started - doing some work
[15:21:38 4519] Child about to signal parent
[15:21:38 4518] Parent got signal
跟原书本P437 不同哦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/697504.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML开发的最主要的三种框架及Python实现

一、介绍 HTML本身是一种标记语言&#xff0c;用于构建网页的结构。然而&#xff0c;当谈到HTML开发框架时&#xff0c;通常指的是那些提供了额外的功能和工具&#xff0c;以帮助开发者更高效地构建网页和应用程序的框架。有三种流行的HTML开发框架&#xff1a; Bootstrap 简介…

基于JSP技术的网络视频播放器

你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 管理员界面 用户界…

网络分析(ArcPy)

一.前言 GIS中的网络分析最重要的便是纠正拓扑关系&#xff0c;建立矫正好的网络数据集&#xff0c;再进行网络分析&#xff0c;一般大家都是鼠标在arcgis上点点点&#xff0c;今天说一下Arcpy来解决的方案&#xff0c;对python的要求并不高,具体api参数查询arcgis帮助文档即可…

渗透测试模拟实战(二)-BlueCMS平台

渗透测试 渗透测试是维护网络安全的重要组成部分&#xff0c;可以帮助组织识别并修复潜在的安全漏洞&#xff0c;减少被恶意攻击的风险。然而&#xff0c;进行渗透测试时必须遵守法律和道德规范&#xff0c;确保所有活动都在授权范围内进行。 环境部署&#xff1a; study2016、…

逆序队专题

逆序对的定义是&#xff0c;在一个数组中&#xff0c;对于下标 ( i ) 和 ( j )&#xff08;其中 ( i < j )&#xff09;&#xff0c;如果 ( a[i] > a[j] )&#xff0c;则称 ((a[i], a[j])) 为数组的一个逆序对。 换句话说&#xff0c;逆序对就是在数组中前面的元素大于后…

分布式事务AP控制方案(上)

分布式事务控制方案 本篇文章给出一种要求高可用性&#xff08;AP思想&#xff09;的分布式事务控制方案 下篇新鲜出炉&#xff1a;点我查看 分布式事务控制方案1、业务背景2、本地消息表的设计3、对消息表的操作4、任务调度5、任务流程控制的抽象类6、课程发布的实现类7、总…

【C++】C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Vue17-条件渲染

一、使用v-show属性做条件渲染 控制元素的显示和隐藏 v-show里面也能是表达式&#xff0c;只要表达式的值是boolean就行。 或者 当时结构还在&#xff1a; 二、使用v-if属性做条件渲染 结构也不在了 三、示例 方式一&#xff1a; 方式二&#xff1a; 当元素有很高的切换频率&am…

机器学习实验----支持向量机(SVM)实现二分类

目录 一、介绍 (1)解释算法 (2)数据集解释 二、算法实现和代码介绍 1.超平面 2.分类判别模型 3.点到超平面的距离 4.margin 间隔 5.拉格朗日乘数法KKT不等式 (1)介绍 (2)对偶问题 (3)惩罚参数 (4)求解 6.核函数解决非线性问题 7.SMO (1)更新w (2)更新b 三、代…

我在得物的这两年

写在前面 这篇文章非常简单&#xff0c;和大家简单聊聊我在得物的这两年&#xff0c;也是从学生到社会人的这两年。 我是2022年的6月加入得物实习&#xff0c;负责某个业务中台的后端研发&#xff0c;那一年我21岁&#xff0c;还在读大三&#xff0c;还在迷茫未来是读研还是工…

nw.js 如何调用activeX控件 (控件是C++编写的dll文件)

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【氵】Archlinux+KDE Plasma 6+Wayland 安装nvidia驱动 / 开启HDR

参考: NVIDIA - Arch Linux 中文维基 &#xff08;其实就是把 wiki 简化了一下 注&#xff1a;本教程适用 GeForce 930 起、10 系至 20 系、 Quadro / Tesla / Tegra K-系列以及更新的显卡&#xff08;NV110 以及更新的显卡家族&#xff09;&#xff0c;此处以 RTX3060 为例 …

Cyber Weekly #10

赛博新闻 1、最强开源大模型面世&#xff1a;阿里发布Qwen2 6月7日凌晨&#xff0c;阿里巴巴通义千问团队发布了Qwen2系列开源模型。该系列模型包括5个尺寸的预训练和指令微调模型&#xff1a;Qwen2-0.5B、Qwen2-1.5B、Qwen2-7B、Qwen2-57B-A14B以及Qwen2-72B。据Qwen官方博客…

1.奖牌的数量

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/447 题目描述 小爱获得了 𝑎a 枚金牌,…

MATLAB实现磷虾算法(Krill herd algorithm)

1.算法介绍 磷虾算法&#xff08;Krill Herd Algorithm, KH&#xff09;是一种基于生物启发的优化算法&#xff0c;其原理模拟了南极磷虾&#xff08;Euphausia superba&#xff09;群体的聚集行为。该算法旨在通过模拟磷虾个体间的相互作用、觅食行为和随机扩散&#xff0c;来…

springboot3一些听课笔记

文章目录 一、错误处理机制1.1 默认1.2 自定义 二、嵌入式容器 一、错误处理机制 1.1 默认 错误处理的自动配置都在ErrorMvcAutoConfiguration中&#xff0c;两大核心机制&#xff1a; ● 1. SpringBoot 会自适应处理错误&#xff0c;响应页面或JSON数据 ● 2. SpringMVC的错…

知识图谱的应用---智慧农业

文章目录 智慧农业典型应用 智慧农业 智慧农业通过生产领域的智能化、经营领域的差异性以及服务领域的全方位信息服务&#xff0c;推动农业产业链改造升级;实现农业精细化、高效化与绿色化&#xff0c;保障农产品安全、农业竞争力提升和农业可持续发展。目前&#xff0c;我国的…

第1章Hello world 4/5:对比Rust/Java/C++创建和运行Hello world全过程:运行第一个程序

讲动人的故事,写懂人的代码 1.7 对比Rust/Java/C++创建和运行Hello world全过程 有了会听懂人类的讲话,还能做记录的编程助理艾极思,他们三人的讨论内容,都可以变成一份详细的会议纪要啦。 接下来,我们一起看看艾极思是如何记录下赵可菲创建和运行Java程序Hello world,…

基于Java-SpringBoot-VUE-MySQL的高校数字化迎新管理系统

基于Java-SpringBoot-VUE-MySQL的高校数字化迎新管理系统 登陆界面 联系作者 如需本项目源代码&#xff0c;可扫码或者VX:bob1638联系作者。 首页图表 系统功能持续更新中。。。 介绍 这是一款主要用于高校迎新的系统&#xff0c;主要是采用了SpringBoot2.X VUE2.6 ElementUI2.…

怎么避免电脑磁盘数据泄露?磁盘数据保护方法介绍

电脑磁盘是电脑存储数据的基础&#xff0c;而为了避免磁盘数据泄露&#xff0c;我们需要保护电脑磁盘。下面我们就来了解一下磁盘数据保护的方法。 磁盘加密 磁盘加密可以通过专业的加密算法来加密保护磁盘数据&#xff0c;避免电脑磁盘数据泄露。在这里小编推荐使用文件夹只读…