**《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 tocomplete 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 不同哦

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“RabbitMQ入门指南:从入门到起飞,这一篇就够!打造高效消息通信系统的第一步“。

1.前言 RabbitMQ是一个开源的消息代理软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;的标准&#xff0c;并用Erlang语言编写。作为消息代理&#xff0c;RabbitMQ接收、存储和转发消息&#xff0c;帮助应用程序之间实现异步通信。它提供了一个强大而灵活…

Qt开发技术:Q3D图表开发笔记(四):Q3DSurface三维曲面图颜色样式详解、Demo以及代码详解

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/139424086 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 红胖子网络科技博…

PawSQL优化 | 分页查询太慢?别忘了投影下推

​在进行数据库应用开发中&#xff0c;分页查询是一项非常常见而又至关重要的任务。但你是否曾因为需要获取总记录数的性能而感到头疼&#xff1f;现在&#xff0c;让PawSQL的投影下推优化来帮你轻松解决这一问题&#xff01;本文以TPCH的Q12为案例进行验证&#xff0c;经过Paw…

Redisson分布式锁原理解析

前言 首先Redis执行命令是单线程的&#xff0c;所以可以利用Redis实现分布式锁&#xff0c;而对于Redis单线程的问题&#xff0c;是其线程模型的问题&#xff0c;本篇重点是对目前流行的工具Redisson怎么去实现的分布式锁进行深入理解&#xff1b;开始之前&#xff0c;我们可以…

Vmess协议是什么意思? VLESS与VMess有什么区别?

VMess 是一个基于 TCP 的加密传输协议&#xff0c;所有数据使用 TCP 传输&#xff0c;是由 V2Ray 原创并使用于 V2Ray 的加密传输协议&#xff0c;它分为入站和出站两部分&#xff0c;其作用是帮助客户端跟服务器之间建立通信。在 V2Ray 上客户端与服务器的通信主要是通过 VMes…

ThinkPHP发邮件配置教程?群发功能安全吗?

ThinkPHP发邮件的注意事项&#xff1f;如何优化邮件发送的性能&#xff1f; 无论是用户注册、密码重置还是消息提醒&#xff0c;发送邮件都是一个常见的需求。AokSend将详细介绍如何在ThinkPHP框架中配置和发送邮件&#xff0c;帮助开发者轻松实现邮件功能。 ThinkPHP发邮件&…

43【PS 作图】颜色速途

1 通过PS让画面细节模糊&#xff0c;避免被过多的颜色干扰 2 分析画面的颜色 3 作图 参考网站&#xff1a; 色感不好要怎么提升呢&#xff1f;分享一下我是怎么练习色感的&#xff01;_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1h1421Z76p/?spm_id_from333.1007.…

【Python教程】3-控制流、循环结构与简单字符串操作

在整理自己的笔记的时候发现了当年学习python时候整理的笔记&#xff0c;稍微整理一下&#xff0c;分享出来&#xff0c;方便记录和查看吧。个人觉得如果想简单了解一名语言或者技术&#xff0c;最简单的方式就是通过菜鸟教程去学习一下。今后会从python开始重新更新&#xff0…

MySQL之查询性能优化(七)

查询性能优化 排序优化 无论如何排序都是一个成本很高的操作&#xff0c;所以从性能角度考虑&#xff0c;应尽可能避免排序或者尽可能避免对大量数据进行排序。前面已经提到了&#xff0c;当不能使用索引生成排序结果的时候&#xff0c;MySQL需要自己进行排序&#xff0c;如果…

人脸考勤项目实训

第一章 Python-----Anaconda安装 文章目录 第一章 Python-----Anaconda安装前言一、Anaconda是什么&#xff1f;二、Anaconda的前世今生二、Windows安装步骤1.官网下载2.安装步骤安装虚拟环境 总结 前言 工欲善其事必先利其器&#xff0c;项目第一步&#xff0c;安装我们的环境…

【Unity UGUI】Screen.safeArea获取异形屏数据失败

Screen.safeArea获取不到异形屏的尺寸位置等数据 检查AndroidManifest.xml文件是否有设置&#xff1a;android:theme"style/UnityThemeSelector"&#xff0c;没有加上即可 android:theme"style/UnityThemeSelector"

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

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

简记:为Docker配置服务代理

简记 为Docker配置服务代理 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/art…

Leetcode3040. 相同分数的最大操作数目 II

Every day a Leetcode 题目来源&#xff1a;3040. 相同分数的最大操作数目 II 解法1&#xff1a;记忆化搜索 第一步可以做什么&#xff1f;做完后&#xff0c;剩下要解决的问题是什么&#xff1f; 删除前两个数&#xff0c;剩下 nums[2] 到 nums[n−1]&#xff0c;这是一个…

分享一个 .NET Core Console 项目中应用 NLog 写日志的详细例子

前言 日志在软件开发中扮演着非常重要的角色&#xff0c;通常我们用它来记录应用程序运行时发生的事件、错误信息、警告以及其他相关信息&#xff0c;帮助在调试和排查问题时更快速地定位和解决 Bug。 通过日志&#xff0c;我们可以做到&#xff1a; 故障排除和调试&#xff…

4.大模型微调技术LoRA

大模型低秩适配(LoRA)技术 现有PEFT 方法的局限与挑战 Adapter方法,通过增加模型深度而额外增加了模型推理延时。Prompt Tuning、Prefix Tuning、P-Tuning等方法中的提示较难训练,同时缩短了模型可用的序列长度。往往难以同时实现高效率和高质量,效果通常不及完全微调(f…

已解决Error || RuntimeError: size mismatch, m1: [32 x 100], m2: [500 x 10]

已解决Error || RuntimeError: size mismatch, m1: [32 x 100], m2: [500 x 10] 原创作者&#xff1a; 猫头虎 作者微信号&#xff1a; Libin9iOak 作者公众号&#xff1a; 猫头虎技术团队 更新日期&#xff1a; 2024年6月6日 博主猫头虎的技术世界 &#x1f31f; 欢迎来…

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

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

mysql 数据库datetime 类型,转换为DO里面的long类型后,只剩下年了,没有了月和日

解决方法也简单&#xff1a; 自定义个一个 Date2LongTypeHandler <resultMap id"BeanResult" type"XXXX.XXXXDO"><result column"gmt_create" property"gmtCreate" jdbcType"DATE" javaType"java.lang.Long&…

软件游戏steam_api.dll丢失的解决方法,总结5种有效的方法

在玩电脑游戏时&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“游戏缺少steam_api.dll”。这个问题可能让很多玩家感到困惑和烦恼。那么&#xff0c;究竟是什么原因导致游戏缺少steam_api.dll呢&#xff1f;又该如何解决这个问题呢&#xff1f;本文将为大家…