父子进程共享资源的关系
Posted 骑单车去旅行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了父子进程共享资源的关系相关的知识,希望对你有一定的参考价值。
fork()
用来创建进程fork(void)
在linux中所有进程都是由init进程直接或间接创建
成功:在父进程中将返回子进程的PID;子进程返回0,以区别父进程
失败:父进程中返回-1
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int main(int argc,char *argv[])
6 {
7 pid_t pid;
8 if((pid=fork())==-1)
9 printf("fork error");
10 printf("bye\n");
11 printf("当前进程的进程号pid:%d\n当前进程的父进程号ppid:%d\n",getpid(),getppid());
12 return 0;
13 }
结果:
[[email protected] PCB]# ps aux
root 3905 0.0 0.1 108468 1904 pts/0 S Dec17 0:00 bash
[[email protected] PCB]# ./fork
bye
bye
当前进程的进程号pid:4570
当前进程的父进程号ppid:3905
pid=fork()中pid的值:4571 //在父进程中将返回子进程的PID
当前进程的进程号pid:4571
当前进程的父进程号ppid:4570
pid=fork()中pid的值:0 //子进程返回0,以区别父进程
子进程中的代码在fork返回位置执行;子进程创建成功之后,和父进程同时执行,竞争系统资源,谁先执行由调度算法决定。
父子进程
子进程会复制父进程的几乎所有信息:子进程复制父进程用户空间所有数据;
子进程复制父进程内核空间PCB中绝大多数数据;
一、文件流缓冲区的资源位于用户空间,所以全部复制。即如果流缓冲区中有临时信息,都会复制到子进程的用户空间流缓冲区中。
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4
5 int main(int argc,char *argv[])
6 {
7 pid_t pid;
8 printf("在fork之前,有回车\n");
9 printf("在fork之前,没有回车,getpid()——pid=%d\t",getpid());
10 pid=fork();
11 if(pid==0)
12 printf("\nfork后创建的子进程getpid()——pid=%d\n",getpid());
13 else
14 printf("\nfork后创建的父进程getpid()——pid=%d\n",getpid());
15 }
[[email protected] PCB]# ./streamfork
在fork之前,有回车
在fork之前,没有回车,getpid()——pid=5536
fork后创建的父进程getpid()——pid=5536
在fork之前,没有回车,getpid()——pid=5536
fork后创建的子进程getpid()——pid=5537
按照上面所说,子进程要在fork方法执行并返回某值后才会复制代码到子进程,子进程从返回值位置向后执行,不会执行之前的代码,但这段代码却输出了之前的代码,这就是复制了缓冲区的缘故。
之所以出现两次输出,有两方面原因,首先是跟printf的缓冲机制有关,我们在前面说过printf("%d",i)=fprintf(stdout,"%d",i),就是说printf函数输出某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有立刻写到屏幕上。但是,只要看到有/n 则会立即刷新stdout,才能够马上打印了。
其次就是因为复制了缓冲区。由于父进程在fork前输出的第二个printf函数时没有回车,而输出流是带缓冲的,从而该信息缓存到用户空间,在fork创建子进程后,系统为子进程复制父进程数据空间以及标准输出缓冲区,子进程刷新了输出缓冲区,将数据输出。
二、子进程复制父进程的数据段,BSS段,代码段,堆空间,栈空间,文件描述符,但是对于文件描述符关联的内核文件表项(即struct file结构体)则是采用共享的方式
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/types.h>
7
8 int main(int argc,char *argv[])
9 {
10 pid_t pid;
11 int fd;
12 int i=1;
13 int status;
14 char *ch1="hello";
15 char *ch2="world";
16 char *ch3="IN";
17 if((fd=open("test.txt",O_RDWR|O_CREAT,0644))==-1)
18 {
19 perror("parent open");
20 exit(EXIT_FAILURE);
21 }
22 if(write(fd,ch1,strlen(ch1))==-1)
23 {
24 perror("parent write");
25 exit(EXIT_FAILURE);
26 }
27 if((pid=fork())==-1)
28 {
29 perror("fork");
30 exit(EXIT_FAILURE);
31 }
32 else if(pid==0)
33 {
34 i=2;
35 printf("in chile\n");
36 printf("i=%d\n",i);
37 if(write(fd,ch2,strlen(ch2)));
38 perror("chile write");
39 return 0;
40 }
41 else
42 {
43 sleep(1);//等待子进程先执行
44 printf("in parent\n");
45 printf("i=%d\n",i);
46 if(write(fd,ch3,strlen(ch3)));
47 perror("parent write