Linux中fork系统调用

来源:互联网 发布:sql日期转换成字符串 编辑:程序博客网 时间:2024/05/17 02:10

1. fork系统调用头文件:<unistd.h>;

2. fork系统调用的原型:pid_t fork();

3. fork系统调用的返回值:pid_t是进程描述符类型,本质就是一个int。如果fork函数执行失败,返回一个负数(<0);如果fork调用执行成功,返回两个值:0和所创建子进程的ID。

4. fork系统调用的功能:以当前进程作为父进程创建出一个新的子进程,并且将父进程的所有资源拷贝给子进程,这样子进程作为父进程的一个副本存在。父子进程几乎时完全相同的,但也有不同的如父子进程ID不同。

5. 注意:当fork系统调用成功时,它会返回两个值:一个是0,另一个是所创建的新的子进程的ID(>0)。当fork成功调用后此时有两个数据相同的父子进程,我们可以通过fork的返回值来判断接下来程序是在执行父进程还是子进程。

pid_t pid = fork();if(pid == 0){      //在子进程中}else if(pid > 0){      //在父进程中}else{     //fork调用失败}
6. fork调用与文件描述符的关系

前面我们知道当我们使用fork系统调用以当前进程作为父进程创建出了一个子进程,父进程将自己的在fork系统调用之前的所有数据和代码都复制一份给子进程,此时子进程相当于父进程的一个拷贝。对于在fork调用之前打开的文件也一样,也会做一个拷贝将文件描述符复制给子进程,这样父子进程可以同时对一个文件进行操作。但是这种操作是共享式的,父子进程共享这个文件描述符所索引的文件。何谓父子进程共享这个文件呢?举个简单例子说明下

如果一个已经打开的txt文件,里边的内容是一个字符串“abcdefg”。在父进程中读取前两个字符“ab”,此时文件指针指向c。如果在子进程中再次读取两个字符,那么它读取就是“cd”,并且读完后文件指针指向e。这就是父子进程以共享的方式来操作文件。下面我们通过代码说明这个关系:

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<iostream>#include<pthread.h>#include<fcntl.h>//为了使用O_RD_ONLYint gb = 10;using namespace std;int main(){int fd = open("fork.txt", O_RDONLY);if(fd < 0)//文件描述符是一个非负整数:0是stdin的文件描述符,1是stdout的文件描述符,2是stderr的文件描述符{cout<<"error in open the file!"<<endl;exit(1);}cout<<"文件描述符为:"<<fd<<endl;char *c = new char[3];int a = 5;cout<<"main函数中的进程ID:"<<getpid()<<endl;pid_t pid = fork();//fork系统调用的作用是:使用当前进程作为副本创建出一个子进程。它会返回两个值,一个是子进程的ID,一个是0if(pid == 0)//在子进程中{read(fd, c, 2);c[2] = '\0';cout << "---------------------------------------------"<<endl;cout << c << endl;gb += 10;a += 10;cout << "gb = " << gb << ",a = " << a << endl;cout << "子进程ID:" << getpid() << ",子进程的父进程ID为:" << getppid() << endl;cout << "子进程中pthread_self():" << pthread_self() << endl;//因为两个pthread_self()函数都是在主线程中的,所以两个获取的线程ID相同}else if(pid > 0)//在当前进程中,也就是父进程中{read(fd, c, 2);c[2] = '\0';cout << "--------------------------------------------"<<endl;cout << c << endl;cout << "gb = " << gb << ",a = " << a << endl;cout << "父进程ID:" << getpid() << ",父进程的父进程ID为:" << getppid() << endl;cout<<"父进程中pthread_self():"<<pthread_self()<<endl;//因为两个pthread_self()函数都是在主线程中的,所以两个获取的线程ID相同}else{cout<<"fork error!"<<endl;exit(1);}close(fd);//关闭文件描述符对应的文件,如果关闭成功返回0,关闭失败返回-1return 0;}
在linux中执行结果:

 

这里我们使用open系统调用打开了一个名为fork.txt的文件,文件中的是一个个字符串。
 (1)文件描述符为3:因为系统中0时stdin的文件描述符,1是stdout的文件描述符,2是stderr的文件描述符。其他的用于索引我们自己打开的文件描述符,每打开一个一个文件就是使用最小的可使用的文件描述符表示。如果再打开一个文件,他的fd是4.

(2)使用getpid()函数可以获取当前进程的ID,使用getppid()可以获取当前进程的父进程的ID,使用pthread_self()可以获取当前线程的ID。

(3)通过结果可以看出我们使用fork创建了子进程并在子进程中对变量gb和a做了修改,但是这个修改并不会影响到父进程中两个变量的值。这是因为fork系统调用将父进程中的变量拷贝一份给子进程中。父子进程中的数据各不相关。

(4)在父进程中使用read系统调用读取文件的前两个字符ab。然后在子进程中再次读取两个字符是cd,而不是ab。这说明父子进程共享同一个文件,它们对文件的操作是同步的。

原创粉丝点击