在Linux 内核中,无时无刻不维护着进程,从进程的创建到进程销毁,每一个环境都有着复杂的细节。本篇介绍Linux 内核如何创建进程,深入理解 fork 函数以及子进程的创建,对理解多进程开发也至关重要。

fork() 函数

首先来看下fork() 函数,其作用是创建子进程。头文件与函数原型如下

#include

// 参数: void

// 返回值: pid_t 创建的子进程ID

pid_t fork(void);

返回值:fork() 返回值会返回两次,分别在父进程和子进程中返回。

在父进程中返回子进程的ID,在子进程中返回0。所以可以通过fork 的返回值来区分父进程与子进程。

在父进程中返回 -1 ,表示创建子进程失败,并设置 errorno。如下面两种情况导致创建失败:当前系统的进程数已经达到了系统规定的上限,这时 errno 的值被设置为EAGAIN

系统内存不足,这时 errno 的值被设置为 ENOMEM

fork() 示例

下面创建一个子进程,来说明父进程与子进程的执行顺序。

#include

#include

int main(){

// 创建进程

pid_t pid = fork();

// 判断当前进程是父进程 还是子进程

if (pid > 0){// 进程号 > 0,即为子进程的进程号,当前为父进程

printf("pid: %dn", pid);

printf("I am parent process, pid: %d, ppid: %dn", getpid(), getppid());

}

else if (pid == 0){// 进程号 == 0,表示当前为子进程

printf("I am child process, pid: %d, ppid: %dn", getpid(), getppid());

}

for (int i = 0; i < 5; i++){

printf("pid: %d, i : %dn", getpid(), i);

sleep(1);

}

return 0;

}

编译执行,可以看到,子进程创建成功,两个进程同时执行,父进程ID 为412552,子进程ID为512553,由于sleep() 函数,使得函数阻塞,所以父进程与子进程交替执行。

父子进程的虚拟地址空间

通过 fork函数创建进程后,可以通过返回值判断是父进程还是子进程。对于父进程与子进程如何执行,下面介绍fork函数调用后,父子进程如何执行,在进程中虚拟地址空间中如何体现。

首先,我们先看一下上述示例的执行顺序,父进程执行执行fork后,返回子进程ID,pid 大于0,所以输出 if(pid>0) 的内容。

子进程在创建成功后,在子进程中返回 0,从当前位置开始执行,所以 pid=0 会输出 else 语句。

对于虚拟空间地址来说,子进程会拷贝父进程的虚拟地址空间。所以,fork后子进程的用户区与父进程的用户区相同,也会拷贝内核区内容,仅仅是进程的 pid不同。

对于父进程中的栈空间的变量,也会原封不动的拷贝至子进程的栈空间中。但这两个变量互不影响,父进程改变变量不会影响子进程变量。看如下程序展示父子进程中栈空间变量的使用。

#include

#include

int main(){

// 创建进程

pid_t pid = fork();

// 局部变量

int num = 10;

// 判断当前进程是父进程 还是子进程

if (pid > 0){// 进程号 > 0,即为子进程的进程号,当前为父进程

printf("I am parent process, pid: %d, ppid: %dn", getpid(), getppid());

printf("parent process num : %dn", num);

num += 10;

printf("parent process num + 10 : %dn", num);

}

else if (pid == 0){// 进程号 == 0,表示当前为子进程

printf("I am child process, pid: %d, ppid: %dn", getpid(), getppid());

printf("child process num : %dn", num);

num += 100;

printf("child process num + 100 : %dn", num);

}

return 0;

}

编译执行,可以看到,父进程中的局部变量num 与子进程的局部变量互不影响。

读时共享,写时拷贝技术

实际上,准确的来说,Linux的fork 是通过 写时拷贝 (copy-on-write)实现。写时拷贝是一种可以推迟甚至不用避免拷贝的技术。更具体来讲,在执行fork语句后,内核并不复制父进程的整个地址空间,而是父子进程共享父进程的地址空间(此时父子进程对于地址空间是只读指令),在父进程或者子进程进行写指令时,子进程才会复制一份地址空间,从而使得父子进程拥有自己的虚拟地址空间,在自己的地址空间进行写操作。也就是说,资源的复制是在需要写入时才会进行,在此之前,只会以只读方式进行共享。

对于文件资源,fork之后的父子进程共享文件,fork之后的父进程与子进程的文件描述符表指向相同的文件表,引用计数增加,共享文件偏移指针。

fork函数就介绍到这里了,本篇介绍了创建子进程的过程,理解父子进程间虚拟地址空间的共享与复制。在多线程开发中,可以轻松分析父子进程的执行顺序与内存共享。

点关注,不迷路。一键三连是对我最大的支持,欢迎关注编程小镇,每天涨一点新姿势

内容来源于网络如有侵权请私信删除

linux创建进程读共享写复制,Linux进程创建之fork浅析相关推荐

  1. linux创建进程读共享写复制,Linux下进程的创建、执行和终止

    1)进程的创建和执行 许多操作系统提供的都是产生进程的机制,也就是说,首先在新的地址空间里创建进程.读入可执行文件,后再开始执行.Linux中进程的创建很特别,它把上述步骤分解到两个单独的函数中去执行 ...

  2. linux中可读可写可执行权限是什么意思,linux chmod 给目录或文件赋权限 可读可写可执行...

    前提: mode权限设定字串,格式:[ugoa...][[+-=][rwxX]...][,...] 其中u表示拥有者(user),g表示与拥有者属于同一个群体(group),o表示其他以外的人(oth ...

  3. otg烧写linux内核,OTG 接口烧写最小Linux的方法

    通过该方式可以烧写Android4.0.3 系统和Linux-QT 系统. 需要准备一根OTG 线,绝大多数智能手机和PC 机相连接的线都是OTG线,都是通用的. 这种方式比TF卡烧写方式要快一些,我 ...

  4. linux增加预读缓存区大小,Linux使用blockdev命令调整文件预读大小的方法

    我们在使用过程中,可以对一些文件选择预读,这可以加快我们的工作效率.不过有时遇到一些较大的文件,就会导致我们的预读不全,那么这个问题该怎么解决呢?今天小编和大家分享下使用blockdev命令设置文件预 ...

  5. linux如何在文件中写命令,Linux中读、执行、写命令(wxr)

    文件属主:读r.写w.执行x 用户组: 读r.写w.执行x 其它用户:读r.写w.执行x 如果权限位不可读.不可写.不可执行,是用-来表示. w表示读,x表示可以执行,r表示读 r对应数字:4 w对应 ...

  6. linux怎么让某一个组对一文件可读可写,设置linux文件权限,使得同一用户组的可以对一个文件自由修改...

    新添用户,设置权限 新增用户的时候设置用户所属组,将想要一起的用户设置到一个组内 usermod -g 用户组 用户名 #这里将用户的主组设置为这个总组,这里为了再之后创建文件的时候文件所属组为这个组 ...

  7. 使用named_mutex实现读写锁,实现进程之间读共享写独占

    代码 代码的名称是read_write_mutex.h 这个代码可用,但是未优化,还存在冗余的代码 如果涉及到进程挂掉了,造成进程堵塞,如何解决?还未涉及 //#ifndef BOOST_THREAD ...

  8. linux如何挂载nfs共享目录,在Linux中,如何挂载NFS共享

    网络文件系统( NFS )是一种分布式文件系统协议,允许你通过网络共享远程目录,使用NFS,可以在系统上挂载远程目录,并像使用本地文件一样使用远程文件. 在Linux和UNIX操作系统上,可以使用mo ...

  9. linux增加预读缓存区大小,Linux blockdev命令设置文件预读大小介绍

    在命令行调用设备的ioctl函数.在Linux系统中,似乎对设备的直接操作只有ioctl函数了.他接受的参数不是太多,而且都是一一对应的. blockdev - 从命令行调用区块设备控制程序 bloc ...

最新文章

  1. 4.struts2的配置文件优先级
  2. QT精彩实例分析第5章-0
  3. Android应用开发—PendingIntent:如何判断两个PendingIntent对等
  4. 论文浅尝 | SPARQL 语言的 ASK 查询表达性研究进展
  5. c winform mysql类_C#连接MySQL数据库操作类
  6. 【算法】斐波那契(黄金分割法) 查找算法
  7. 大小字节序的深入理解和鉴定系统字节序方法
  8. AWT_addKeyListener键盘监听事件(Java)
  9. iOS开发那些事--nib、xib与故事板的关系
  10. MapGIS67二次开发环境搭建
  11. AI人机对战五子棋游戏【Python(pygame)+AI】并实现软件输出
  12. lintcode刷题——罗马数字转整数
  13. Android打包动态配置签名
  14. CH模拟赛 皇后游戏
  15. 深度学习基础--输出层的神经元数应该与分类数匹配(分类数大于等于2)则是一个监督学习任务,对吗?
  16. 古籍、中国通史、诗经、辞、、四书五经、诸子百家、四大名著、唐诗、宋词、明清小说、四库全书
  17. Transformer Architectures and Pre-training Strategies for Fast and Accurate Multi-sentence Scoring
  18. 指定FPS帧频,requestAnimationFrame播放动画
  19. Nwafu-OJ-1430 Problem a C语言实习题五——5.用指针实现查找二维数组中最大数及其位置
  20. 智慧园区信息化解决方案,未来园区发展新方向

热门文章

  1. vue项目中导入icon字体文件出现This relative module was not found:* ./iconfont.eot?t=1523541245904
  2. vue项目图片插入不清晰,原因分析及解决办法
  3. 裁剪任意直线段 liang-barshky算法 c
  4. Echarts动态饼状图,柱形图,关系图绘制
  5. archlinux配置conky
  6. 如何注册安全邮箱?- 企业电子邮件域名。
  7. 备考心得100天PMP通关经验分享
  8. 【PWA】web推送技术
  9. Java日记_17.9.01——点击按钮后,键盘监听失效的原因与解决办法
  10. core java文献翻译_外文翻译--Java技术介绍(适用于毕业论文外文翻译+中英文对照).doc...