linux 的fork函数原型,【操作系统】关于fork()
发布日期:2021-06-24 15:51:46 浏览次数:4 分类:技术文章

本文共 2030 字,大约阅读时间需要 6 分钟。

fork函数的原型

pid_t fork();

返回值:若成功调用,一次则返回两个值,子进程返回0,父进程返回子进程的进程id,否则,出错返回-1.

调用fork时发生的事

一个进程调用fork()函数后,系统中出现两个基本完全相同的进程,子进程从父进程处继承了整个进程的地址空间,包括进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端, 父子进程不共享这些存储空间部分,父子进程共享正文段。这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。

父子进程的id是不同的。

父进程设置了锁,子进程不继承。

子进程的未决告警被清除

子进程的未决信号集设置未空集

fork可能出错的原因

当前进程数量已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。

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

更多关于

Unix标准的复制进程的系统调用fork(即分叉),但是Linux,BSD等操作系统并不止实现这一个,确切地说linux实现了三个,fork、vfork、clone(确切地说,vfork创造出来的是轻量级进程,也叫线程,是共享资源的进程)系统调用:fork创造的子进程是父进程的完整副本,复制了父亲进程的资源,包括内存的内容task_struct内容;vfork创建的子进程和父进程共享数据段,而且由vfork创建的子进程将先于父进程运行;clone,linux上创建线程一般使用的是pthread库,实际上linux也给我们提供了创建线程的系统调用,就是clone;

写时复制

有人认为这样大批量的复制会导致执行效率过低(第一代linux是这样的)。其实在复制过程中,linux采用了写时复制的策略。子进程复制了父进程的task_struct,系统堆栈空间和页表,在子程序修改变量之前,这些变量空间都指的是同一块内存。而当子进程改变变量时(写操作),会通过copr_on_write手段为所涉及的页面建立一个新的副本。所以当写操作时,子进程才新建一个页面复制原来的内容,基本资源的复制是必须的,而且也是高效的。整体看上去就像父进程的独立空间也复制了一遍。

写时复制(copy_on_write)是一个被使用在程序设计领域的最佳化策略。其基础的观念是,如果有多个呼叫着(callers)同时要求相同的资源,他们会共同取得相同的指标指向相同的资源,直到某个caller尝试修改资源时,系统才会真正复制一个副本(private copy)给该caller,以避免被修改的资源被直接察觉到,这过程对其他的呼叫只都是通透的(transparently)。此做法主要的优点是如果caller没有修改资源,则不会有(private copy)副本被建立。

所以父子进程共享页帧,而不是复制页帧。只要页帧被共享,他们就不能被修改,即页帧保护。无论父进程还是子进程何时试图写一个共享的页帧,就产生一个异常,这时内核就把这个页复制到一个新的页帧中并标记为可写。原来的页帧仍然是写保护的:当其他进程试图写入时,内核检查谢金成是否是这个页帧的唯一属主,如果是,就把这个页帧标记为对这个进程是可写的(取消共享标记)。所以A→fork B,B会拥有A一样的物理页面,B也只能以只读的方式进入A的物理页面,同时A自身也是只读。当A或B对共享的物理页面执行写操作时,都会产生页面出错异常(page_fault int 14)中断,此时CPU会执行系统提供的异常处理函数do_wp_page()来解决这个异常。

do_wp_page()会对这块导致写入异常中断的物理页面进行取消共享的操作,为写进程复制一新的物理页面,使父子进程各自拥有一块内容相同的物理页面。最后,从异常处理函数中返回时,CPU会重新执行刚才的写入操作指令,使进程继续执行下去。vfork不仅使用和父进程相同的物理页面,虚拟页面也会直接共享,子进程的创建还会导致父进程挂起,除非子进程exit或者execve才会唤起父进程。

vfork创建的子进程不应使用return返回调用者,或者使用exit退出,但可以使用_exit()来退出。

vfork与fork区别与联系

vfork父子进程共享数据段,fork子进程拷贝父进程数据段。

fork父子进程执行顺序不定,vfork保证子进程先运行。vfork保证子进程先运行,在它嗲用exec或_exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。在调用exec或_exit之前与父进程是数据共享的,在它调用exec或_exit之后父进程才可能被调度运行。如果在调用这两个函数之前需要依赖父进程进一步动作,则会导致死锁。当需要改变共享数据段中变量的值,则拷贝父进程。

clone(待补充)

参考:

转载地址:https://blog.csdn.net/weixin_33642922/article/details/116774968 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:linux 图标root运行,linux – 从启动器以root身份运行Pycharm
下一篇:linux 网卡管理,Linux 网卡高级管理

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月16日 07时52分48秒