fork()函数详解
目录
1.基本了解:
2.fork函数的了解:
3.僵死进程:
4. fork和多线程:
1.多线程中某个线程调用 fork(),子进程会有和父进程相同数量的线程吗?
2.父进程被加锁的互斥锁 fork 后在子进程中是否已经加锁?
5.写时拷贝:
1.基本了解:
一个进程,包括代码、数据和分配给进程的资源。fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1。
为什么两个进程的fpid不同呢,这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
2.fork函数的了解:
pid_t fork(void);
函数返回类型 pid_t 实质是 int 类型,Linux 内核 2.4.0 版本的定义是:
typedef int _kenrnel_pid_t;
typedef _kenrnel_pid_t pid_t;
fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。
在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1(此时才能更好理解他的返回值)。
举个例子:
1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <assert.h>6 7 int main()8 { char * s = NULL;9 int n = 0;10 11 pid_t pid = fork();12 assert( pid != -1 );13 if ( pid == 0 )14 {15 s = "child";16 n = 4;17 }18 else19 {20 s = "parent";21 n = 10;22 }23 24 int i = 0;25 26 for(; i < n; i++ )27 {28 printf("pid=%d,s=%s\n",getpid(),s);29 sleep(1);30 }31 32 exit(0);33 }
来看看运行结果:
共打印了4次child,10次parent。fork()产生的子进程打印了4次child.
此时还应注意fork()产生的子进程和父进程之间的并发问题。
3.僵死进程:
(1) 僵死进程概念:子进程先于父进程结束,父进程没有调用 wait 获取子进程退出码。
(2)僵死进程的危害:
- 僵死进程的PID还占据着,意味着海量的子进程会占据满进程表项,会使后来的进程无法fork.
- 僵尸进程的内核栈无法被释放掉,为啥会留着它的内核栈,因为在栈的最低端,有着thread_info结构,它包含着 struct_task 结构,这里面包含着一些退出信息
(3)如何处理僵死进程:父进程通过调用 wait()完成。
wait函数:
pid_t wait(int *status);
进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
下面看例子:
1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <assert.h>6 #include <sys/wait.h>7 int main( int argc, char* argv[], char* envp[])8 { char * s = NULL;9 int n = 0;10 11 pid_t pid = fork();12 assert( pid != -1 );13 if ( pid == 0 )14 {15 s = "child";16 n = 4;17 }18 else19 {20 s = "parent";21 n = 10;22 23 int val = 0;24 int id = wait(&val);25 26 if ( WIFEXITED(val) )27 {28 printf("id=%d,val=%d\n",id,WEXITSTATUS(val));29 }30 }31 int i = 0;32 33 for(; i < n; i++ )34 {35 printf("pid=%d,s=%s\n",getpid(),s);36 sleep(1);37 }38 39 exit(0);40 }
运行结果如图:
引入wait函数可以使先处理完子进程,再去处理父进程。可以有效避免僵死进程。
4. fork和多线程:
1.多线程中某个线程调用 fork(),子进程会有和父进程相同数量的线程吗?
在Linux中,fork的时候只复制当前线程到子进程,也就是说除了调用fork的线程外,其他线程在子进程中“蒸发”了。
2.父进程被加锁的互斥锁 fork 后在子进程中是否已经加锁?
调用fork的时候,会复制父进程的所有锁到子进程中。
假设在fork之前,一个线程对某个锁进行的lock操作,即持有了该锁,然后另外一个线程调用了fork创建子进程。可是在子进程中持有那个锁的线程却"消失"了,从子进程的角度来看,这个锁被“永久”的上锁了,因为它的持有者“蒸发”了。
5.写时拷贝:
传统的fork()系统调用直接把所有的资源复制给新创建的进程。这种实现过于简单并且效率低下,因为它拷贝的数据也许并不共享,更糟的情况是,如果新进程打算立即执行一个新的映像,那么所有的拷贝都将前功尽弃。Linux的fork()使用写时拷贝(copy-on-write)页实现。
写时拷贝是-一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。在页根本不会被写入的情况下——举例来说,fork()后立即调用exec()—-它们就无需复制了。fork()的实际开销就是复制父进程的页表以及给子进程创建惟一的进程描述符。在一般情况下,进程创建后都会马上运行一个可执行的文件,这种优化可以避免拷贝大量根本就不会被使用的数据(地址空间里常常包含数十兆的数据)。由于Unix强调进程快速执行的能力,所以这个优化是很重要的。
fork()函数详解相关推荐
- 【Linux系统编程】fork()函数详解
00. 目录 文章目录 00. 目录 01. 进程创建函数 02. 父子进程结构 03. 父子进程地址空间 04. 附录 01. 进程创建函数 #include <sys/types.h> ...
- Linux中fork()函数详解
Linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...
- getpid php,对python中的os.getpid()和os.fork()函数详解
如下所示: import os import sys import time processNmae = 'parent' print "Program executing ntpid:%d ...
- linux中的fork函数详解
在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程.在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID.我们可以通过fork返回的值来 ...
- 【Linux系统编程】fork() 函数详解
需要的头文件: #include <sys/types.h> #include <unistd.h> pid_t fork(void); 功能: 用于从一个已存在的进程中创建一 ...
- Linux中fork函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不 ...
- fork函数详解(fork就是分叉的意思, 很形象)
转载地址: http://blog.sina.com.cn/s/blog_7582409f0100v6cp.html, 感谢原创者. (注意: 代码中的/n貌似应该是\n) ...
- fork函数详解(转载)
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同 ...
- linux中fork函数详解,fork() 函数详解
fork() 函数是 linux/unix 下一种特别的创建子进程的函数,它不同与 Windows,这个函数在执行成功后会有两个返回值,一个返回值==0代表创建了子进程,一个返回值大于0代表还是当前程 ...
- linux fork函数详解
引言 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做 ...
最新文章
- PHP创建日志记录(已封装)
- COJ 0995 WZJ的数据结构(负五)区间操作
- ISE和Modelsim联合仿真
- python定义字符串数组_从字符串数组(或元组)在Python中创建动态sql“ in list”子句的“最佳”方法是什么?...
- SpringCloud学习(八)消息总线(Spring Cloud Bus)(Finchley版本)
- iptables详解以及企业常用案例
- lambdas for_Java 8发布了! — Lambdas教程
- python读取word文档结构图_python根据文章标题内容自动生成摘分享的实例
- Nokia Lumia(WP7.5) 新手入门的摸索
- mac php fpm 自动启动,mac系统,php-fpm加入开机启动项
- arcgis怎么压缩tif文件_pdf文件过大怎么办?3种免费压缩PDF的方法
- 渲染巨匠(lightscape) 3.2 SP1 汉化版
- 华为内部转岗最好时间_华为博士类员工离职率21.8%:平均年薪110万,依然度日如年...
- 淘宝网站的设计与排版
- Win7怎么进入注册表(regedit)
- Facebook币Libra学习-6.发行属于自己的代币Token案例(含源码)
- php 视频添加水印,记php调用ffmpeg给视频加文字水印
- C语言 文件操作 深度解析 #重点知识:文件操作函数的使用#
- 【SSM直击大厂】第十三章:MyBatis 详解
- 在Dreamwaver上基于HTML编写自己的