孤儿进程与僵尸进程
孤儿进程:
如果父进程先退出,子进程还没退出那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)
-
- int main(int argc, char *argv[])
- {
- pid_t pid = fork();
- if (pid < 0)
- err_exit("fork error");
- else if (pid > 0)
- exit(0);
- else
- {
- sleep(10);
- cout << "Child, ppid = " << getppid() << endl;
- }
- exit(0);
- }
僵尸进程:
如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵尸进程。
-
- int main(int argc, char *argv[])
- {
- pid_t pid = fork();
- if (pid < 0)
- err_exit("fork error");
- else if (pid == 0)
- exit(0);
- else
- {
- sleep(50);
- }
- exit(0);
- }
附-查询父子进程状态
ps -le | grep main
避免僵尸进程
signal(SIGCHLD, SIG_IGN);
-
- int main(int argc, char *argv[])
- {
- signal(SIGCHLD, SIG_IGN);
- pid_t pid = fork();
- if (pid < 0)
- err_exit("fork error");
- else if (pid == 0)
- exit(0);
- else
- {
- sleep(50);
- }
- exit(0);
- }
文件共享
父进程的所有文件描述符都被复制到子进程中, 就好像调用了dup函数, 父进程和子进程每个相同的打开文件描述符共享一个文件表项(因此, 父子进程共享同一个文件偏移量);

-
- int main(int argc, char *argv[])
- {
- signal(SIGCHLD, SIG_IGN);
-
- int fd = open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);
- if (fd == -1)
- err_exit("file open error");
-
- cout << "We Don`t flash memory\n";
-
- char buf[BUFSIZ];
- bzero(buf, sizeof(buf));
-
- pid_t pid = fork();
- if (pid < 0)
- err_exit("fork error");
- else if (pid > 0)
- {
- strcpy(buf, "Parent...");
- write(fd, buf, strlen(buf));
- close(fd);
- cout << "fd = " << fd << endl;
- exit(0);
- }
- else if (pid == 0)
- {
- strcpy(buf, "Child...");
- write(fd, buf, strlen(buf));
- close(fd);
- cout << "fd = " << fd << endl;
- exit(0);
- }
- }
fork VS vfork
在UNIX/Linux中的fork还没实现copy on write(写时复制)技术之前。Unix设计者很关心fork之后立刻执行exec所造成的地址空间浪费,所以引入了vfork系统调用。其中,vfork子进程与父进程共享数据段,并不真正复制父进程内存,因此在vfork之后执行exec系列函数,并不会导致地址空间浪费以及无用的空间复制时间.而且,即使fork实现了copy on write,效率也没有vfork高.
但是,vfork有个限制,子进程必须立刻执行_exit或者exec系列函数。因此我们不推荐使用vfork,因为几乎每一个vfork的实现,都或多或少存在一定的问题(可以尝试在vfork之后的子进程中既不执行_exit,也不执行exec函数)。
fork与vfork的区别
1. fork子进程拷贝父进程的数据段(但是现在提供了写时复制技术,只有当子进程真正需要写内存时,才复制出该内存的一段副本),因此,在父进程/子进程中对全局变量所做的修改并不会影响子进程/父进程的数据内容.
vfork子进程与父进程共享数据段,因此父子进程对数据的更新是同步的;
2. fork父、子进程的执行次序是未知的,取决于操作系统的调度算法
vfork:子进程先运行,父进程后运行;
-
-
-
- int main()
- {
- int iNumber = 0;
- pid_t pid = vfork();
-
- if (pid == -1)
- {
- perror("fork");
- return -1;
- }
- else if (pid > 0)
- {
- cout << "In Parent Program..." << endl;
- cout << "iNumber = " << iNumber << endl;
- cout << "pid = " << static_cast<int>(getpid());
- cout << "\t ppid = " << static_cast<int>(getppid()) << endl;
-
- }
- else if (pid == 0)
- {
- iNumber ++;
- cout << "In Child Program..." << endl;
- cout << "iNumber = " << iNumber << endl;
- cout << "pid = " << static_cast<int>(getpid());
- cout << "\t ppid = " << static_cast<int>(getppid()) << endl;
-
- }
-
- return 0;
- }
-
- int main()
- {
- int iNumber = 10;
- cout << "Before vfork, pid = " << getpid() << endl;
-
-
- pid_t pid = vfork();
-
- if (pid == -1)
- err_exit("fork");
- else if (pid > 0)
- {
- sleep(4);
- cout << "Parent, iNumber: " << iNumber << endl;
- }
- else if (pid == 0)
- {
- ++ iNumber;
- cout << "Child, iNumber = " << iNumber << endl;
- _exit(0);
- }
-
- return 0;
- }
-
- int main()
- {
- int iNumber = 0;
- pid_t pid = vfork();
-
- if (pid == -1)
- {
- perror("fork");
- return -1;
- }
- else if (pid > 0)
- {
- cout << "In Parent Program..." << endl;
- cout << "iNumber = " << iNumber << endl;
- cout << "pid = " << static_cast<int>(getpid());
- cout << "\t ppid = " << static_cast<int>(getppid()) << endl;
-
- }
- else if (pid == 0)
- {
- iNumber ++;
- cout << "In Child Program..." << endl;
- cout << "iNumber = " << iNumber << endl;
- cout << "pid = " << static_cast<int>(getpid());
- cout << "\t ppid = " << static_cast<int>(getppid()) << endl;
-
-
- execve("./hello",NULL,NULL);
- _exit(0);
- }
-
- return 0;
- }
-
- int main()
- {
- int iNumber = 0;
- pid_t pid = vfork();
-
- if (pid == -1)
- {
- perror("fork");
- return -1;
- }
- else if (pid > 0)
- {
- cout << "In Parent Program..." << endl;
- cout << "iNumber = " << iNumber << endl;
- cout << "pid = " << static_cast<int>(getpid());
- cout << "\t ppid = " << static_cast<int>(getppid()) << endl;
-
- }
- else if (pid == 0)
- {
- iNumber ++;
- cout << "In Child Program..." << endl;
- cout << "iNumber = " << iNumber << endl;
- cout << "pid = " << static_cast<int>(getpid());
- cout << "\t ppid = " << static_cast<int>(getppid()) << endl;
-
-
- char *const args[] = {(char *)"/bin/ls", (char *)"-l", NULL};
- int res = execve("/bin/ls",args,NULL);
- if (res == -1)
- {
- perror("execve");
- _exit(1);
- }
- _exit(0);
- }
-
- return 0;
- }