板凳----《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/715417.html

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

相关文章

2024上半年软考---江苏考区最先公布成绩

经历了考试之后&#xff0c;最期待的就是考试成绩的公布了&#xff0c;最好的成绩是45、45、45.只要过了分数线就满足了。下面我们来看看各大考区的分数的公布时间。 提前说下江苏考区的时间比较早&#xff0c;我就是江苏考区的&#xff0c;希望本次可以顺利通过考试。 2024年…

【全栈实战】大模型自学:从入门到实战打怪升级,20W字总结(一)

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本栏讲解【全栈实战】大模型自学&#xff1a;从入门到实战打怪升级。 &#x1f514;专栏持续更新&#xff0c;适合人群&#xff1a;本科生、研究生、大模型爱好者&#xff0c;期…

React 中的事件处理

React 中是如何处理事件的&#xff0c;现在下面简单的一段代码&#xff1a; export default function App() {const AList lazy(()>import(./List.js))const r useRef(null) const [show, setShow] useState(false);return (<><button onFocus{()>{setShow…

数据可视化案例

数据可视化案例 使用豆瓣电影中的数据来进行可视化&#xff0c;网址&#xff1a;豆瓣电影 Top 250 (douban.com) 一、网页数据分析 我们需要爬取的是豆瓣电影Top250网页每一页的电影名称、图片链接、导演、年份、国家、电影类型、电影评分这些数据。 在待爬取的网页中&#x…

17岁中专女生,闯进全球数学竞赛12强

今年阿里的数学竞赛结果出来了&#xff0c;在榜单的前列包含一个 17 岁的中专女生。 在 2018 年时&#xff0c;阿里巴巴达摩院发起了一个国际数学竞赛&#xff0c;基本每年举办一次&#xff0c;参赛不设报名条件&#xff0c;向全球所有数学爱好者开放&#xff0c;竞赛由阿里创…

AOSP平台开发的利器——Android Studio for Platform

Android Studio for Platform (ASfP) 是一个为使用 Soong 构建系统构建的 Android 开源项目&#xff08;AOSP&#xff09;平台开发者而设计的 Android Studio IDE 版本。与标准 Android Studio 不同&#xff0c;ASfP 具有多语言支持&#xff0c;可以在同一 IDE 中编写 C、Kotli…

java高级——Arrays工具类(包含核心的归并和二分排序以及多个底层知识点)

java高级——Arrays工具类 前情提要文章介绍提前了解的知识点1 二分查找思想 Arrays常用方法介绍&#xff08;8大类&#xff09;1. 创建数组1.1 copyOf&#xff08;&#xff09;1.2 copyOfRange&#xff08;&#xff09;1.3 fill&#xff08;&#xff09; 2. 数组转集合&#x…

数据库-数据定义和操纵-初始MySQL数据库

连接数据库&#xff1a; mysql -u用户名 -p密码 创建数据库&#xff1a; create database 数据库名; 命令查看MySQL中已存在的数据库 show database; 数据库中创建表的规则&#xff1a; CREATE TABLE 表名 (字段名,数据类型,字段名,数据类型,..... ) eg: 首先创建数据库&am…

操作系统—页表(实验)

文章目录 页表1.实验目标2.实验过程记录(1).增加打印页表函数(2).独立内核页表(3).简化软件模拟地址翻译 3.实验问题及相应解答问题1问题2问题3问题4 实验小结 页表 1.实验目标 了解xv6内核当中页表的实现原理&#xff0c;修改页表&#xff0c;使内核更方便地进行用户虚拟地址…

youlai-boot项目的学习—工程构建与运行

开发环境 系统:mac OS Ventura 13.2.1 终端: item2 Homebrew: 4.3.5 IDE: IntelliJ IDEA 2024.1.1 (Ultimate Edition) 代码分支 仓库&#xff1a;https://gitee.com/youlaiorg/youlai-boot.git 分支&#xff1a; master commit: 9a753a2e94985ed4cbbf214156ca035082e02723 …

python数据分析---ch11 python数据描述性统计

python数据分析--- ch11 python数据描述性统计 1. Ch11--描述性统计2. 数据集中趋势的度量2.1 平均值2.2 中位数2.3 众数2.4 几何平均值2.5 调和平均值 3. 数据离散趋势的度量3.1 极差3.2 平均绝对偏差(MAD)3.3 方差和标准差3.4 下偏方差和下偏标准差3.5 目标下偏方差和目标下偏…

【Qt项目专栏】贪吃蛇小游戏1.0

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 贪吃蛇小游戏1.0 项目编号&#xff1a;01 文章目录 贪吃蛇小游戏1.0一…

生信技能48 - 如何获取基因的SNP及RefSeq参考序列命名规则

1. SNP概念 SNP 是指基因组水平上由单个核苷酸的变异所引起的DNA 序列多态性,在群体中的发生频率不小于1 %,包括单个碱基的转换、颠换、插入和缺失等。每核苷酸发生突变的概率大约为10 -9 , 由于压力选择,SNP在单个基因和基因组以及动物不同种群间分布是不均匀的,在非编码…

虚拟机使用桥接模式网络配置

1、获取本机的网络详细信息 windowr 输入cmd 使用ipconfig -all 一样即可 在自己的虚拟机中设置网络 虚拟机中的ip ---------192.168.36.*&#xff0c;不要跟自己的本机ip冲突 网关-----------192.168.36.254 一样即可 dns -----------一样即可&#xff0c;我多写了几个&am…

C | 在ubuntu22下开发的一些配置

目录 VScode设置 要下载的插件&#xff1a; 卸载VScode的话就是哪装的哪删。 浅用gcc 预处理指令 使用gcc 语言编译过程 1. 预处理&#xff08;Preprocessing&#xff09; 2. 编译&#xff08;Compilation&#xff09; 3. 汇编&#xff08;Assembly&#xff09; 4. …

最长回文子串问题详解

最长回文子串的问题描述&#xff1a;给出一个字符串S&#xff0c;求S的最长回文子串的长度。 针对这个问题&#xff0c;先看暴力解法&#xff1a;枚举子串的两个端点i和j&#xff0c;判断在[i,j]区间内的子串是否回文。从复杂度上来看&#xff0c;枚举端点需要&#xff0c;判断…

Linux、Windows安全加固

为了减少系统被黑客入侵&#xff0c;对操作系统的安全加固是网络安全和主机安全必不可少的一部分。 一、Linux安全加固 1.不使用默认的ssh端口&#xff0c;修改默认ssh22端口号 sudo vim /etc/ssh/ssh_config 去掉#注释&#xff0c;修改端口号并保存 2.关闭不必要的系统服务…

芯片验证分享8 —— 代码审查2

大家好&#xff0c;我是谷公子&#xff0c;上节课给大家讲了代码审查中的代码正向检查&#xff0c;今天我们来讲代码审查的其他方法。 今天介绍的检查方法有&#xff1a; 代码反向检查 桌面检查 同行评审 可用性验证 这些验证方法可以应用在芯片开发的任何阶段。代码审查…

vitepress搭建的博客系统cdn引入github discussions评论系统

github仓库必须是公开的。 按照CDN的方式引入 打开discussions模块 安装giscus app 配置giscus 就是刚安装了giscus app的仓库 页面往下走&#xff0c;生成了代码&#xff1a; 配置vitepress 采用了CDN的方式引入 使用web component 随便找个地方试试组件 效果 有了…

Windows 托盘图标实现类封装及使用(附源码)

在系统桌面右下角的托盘区域,创建一个托盘图标,已经是很多软件的标配了,特别是IM即时通讯软件,要在托盘图标上显示来消息时的闪动头像。 其实托盘图标创建很简单,使用起来也比较方便,主要是调用Shell_NotifyIcon API函数,传入不同参数表示对应的操作: 1)NIM_AD…