开发者学堂课程【物联网开发- Linux 高级程序设计全套视频:子进程继承父进程缓冲区 】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/660/detail/10987
子进程继承父进程缓冲区
内容简介:
一、前言
二、代码实现及说明
三、检验是否继承
一、前言
看以下例子,此例子是验证什么?
以前讲过像 printf 等这些函数是带缓冲区的,其中以前提到过 openread 、 write 、 read 和 write ,是系统调用级的接口函数,但是 I/O 函数是不带缓冲区的,比如如果 write 文件里面写东西,它就立马会进入文件,它不会存到缓冲区里面,系统调用级的 I/O 函数是不带缓冲区的,然后这一个代码是验证了父进程如果有一个缓冲区的,且缓冲区里面有东西,它会继承给子进程,因为缓冲区就是一块内存,它是继承给子进程的。
二、代码实现及说明
1、输入例子中的代码
先看一下以下代码:
#include <stdio.h>
#include <stdlib,h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
pid_t pid;
int length = 0
char buf[] = “a write to stdout\n”;
length = write(1, but,strlen(buf));
if(length != strlen(buf));
{
printf(“write error\n”);
}
printf(“before fork\n”);
pid=fork();
if(pid<0)
{
perror(“fork”);
}
else if(pid==0)
{
printf(“in son process\n”);
}
else
{
sleep(1);
printf(“in father process\n”)
}
return 0;
}
2、点斜杠执行及相关说明
(1)说明及内容
注意创建进程时的一些特点,看以上代码,在这个程序当中它定义了一个字符数组,看 write 函数往哪写, fd 是1,1代表标准输出,往标准输出及屏幕上写 buffer 指向的字符串有很多个字节,把“a write to stdout\n”字符串写到标准输出设备软件及屏幕上去,然后当执行第11行的时候,屏幕上立马就又多了一个“a write to stdout\n”,然后判断如果出错的话如何处理,如果不出错它就继续往下执行。
注意 printf 是缓缓冲,因为缓冲区里面有反斜杠n,于是“ before fork ”这句话又到了屏幕上,假如这是咱们的屏幕,当运行程序的时候,在终端里已经打印了两句话了,然后接下来它 fork , fork 之后创建子进程,子进程直接去打 printf (“in son process\n”)这句话,而父进程先 sleep 挂起,所以肯定是“in son process”这一句话被打到屏幕上,这句话是子进程打入的,一秒钟之后,父进程再去打printf(“in father process\n”)这句话,子进程再打完之后,Return 0结束了,父进程一秒钟之后打 in father 这句话,也结束了,所以如果点斜杠执行,
打印的就是以下这种效果:
a write to stdout
before fork
in son process
in father process
(2)运行结果及分析
①运行
先看一下此程序运行结果是不是想要的,格式转为 UTF8 无 BOM 格式,
执行结果如下:
[01_day]./fork2
in son process var=11,num=10
common code area
in father process var=10,num=9
common code area
[01_day]gcc fork3.c -o fork3
[01_day]./fork3
a write to stdout
before fork
in son process
in father process
②结果分析
和以上分析的一模一样,点斜杠执行的时候,它其实父进程的缓冲区里面是没东西的,因为父进程的缓冲区 printf 的时候被刷新了,有反斜杠 n ,而且要 write 的时候,它就是不带缓冲的。
3、去掉点斜杠n执行及相关说明
(1)说明及内容
现在改一下上述代码,拓展一下,如果把 before folk.\n 中的“./n”去掉,那它父进程 before folk 的时候, before folk 应该是在缓冲区里,然后到 folk 的时候,在父进程的缓冲区会打入 before folk ,接下来它没有刷新缓冲区在 printf 的时候,因为 printf是缓缓冲,它没有反斜杠 n 不刷新缓冲区,然后它就 folk ,这样的话缓冲区就被子进程继承了,注意子进程的缓冲区有 before folk ,父进程有个 before folk 在缓冲区里面,子进程当中也有,然后接下来它folk创建子进程了之后,在子进程当中打 printf(“in son process\n”),注意 in son process 这句话是 printf 的,首先它先打到缓冲区里边,因为有反斜杠 n ,所以它把缓冲区里全部刷新,刷新到屏幕上,
注意 a write to stdout还是要执行,父进程当中首先有这句话,注意第一个 before folk是谁刷到屏幕上的,是子进程刷到屏幕上的,然后过了一秒钟之后父进程打印 in father process 这句话, Printf 首先会把数据打到缓冲区里边,因为打印的时候有反斜杠 n ,所以它会刷新缓冲区,把父进程当中的缓冲区刷到屏幕上。
(2)运行结果及分析
①运行上述代码
这个程序的运行结果就变成这样:
a write to stdout
before fork
in son process
before fork
in father process
②对以上结果进行分析及改进
注意第一个 before folk 是子进程刷出来的,第二个 before folk和 in father process 是父进程刷出来的,因为把反斜杠 n 去掉了之后,就使得在创建子进程的时候,缓冲区里面是有东西继承了给子进程。将以上代码运行一下,看看第一次的时候是不是如分析的一样运行的,即只有一个 before folk ,
运行代码如下所示:
[01_day]./fork3
a write to stdout
before fork
in son process
③再次编译进行运行
然后再次编译,将反斜杠 n 去掉之后,运行代码如下所示:
[01_day]gcc fork3.c -o fork3
[01_day]./fork3
a write to stdout
before forkin son process
before forkin father process
④对以上结果分析及改进
所以当把反斜杠 n 去掉了之后,屏幕上应该是这种效果,before folk 后边没有反斜杠 n 了,效果如下:
a write to stdout
before forkin son process
before forkin father process
⑤再次编译进行运行
验证了子进程可以继承父进程的缓冲区,一会先写这个代码,写了这个代码之后再将反斜杠n去掉,看看效果是不是多了一个 before folk 。
4、带着反斜杠 n 运行
(1)说明及效果
其实还有一种运行方式,带着反斜杠 n 运行这个程序的时候,是以下这种效果:
[01_day]./fork3
a write to stdout
before fork
in son process
in father process
(2)对以上进行分析及改进
只有一个 before folk ,但是如果逆向的输入 aaa.txt ,什么意思?这个程序的输出到屏幕上的东西重逆向到文件里面去了,输出到普通文件里面去了,注意这时 printf 就由缓缓冲变成了全缓冲,也就是说在这种运行方式下,在执行 printf 的时候,即便是有反斜杠 n ,它也不刷新缓冲区了,因为它已经不是缓缓冲了,它变成了全缓冲,因为缓缓冲是碰到反斜杠n才刷新缓冲区,而全缓冲碰到反斜杠 n 它也不刷新,那么什么时候刷新?
当缓冲区满了、程序结束了、或者是人为的刷新缓冲区,所以这种情况也能将 before folk 继承给子进程,因为有反斜杠n它也不刷新缓冲区。
三、检验是否继承
看看能不能继承,先输入以下代码:
[01_day]./fork3 > aaa.txt
[01_day]vi aaa.txt
执行结果如下:
a write to stdout
before fork
in son process
before fork
in father process
可以看到有两个 before folk ,其中“before fork in son process”
是子进程刷进来的,“before forkin father process”是父进程刷进来的,那么这两个代码用了两种方式,改了一种方式,另外一种方式运行的时候重合了,然后验证了子进程可以继承父进程的缓冲区。