0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

fork出的进程的父进程是从哪来的

电子设计 来源:电子设计 作者:电子设计 2020-12-24 18:41 次阅读

一、粉丝提问

fork出的进程的父进程是从哪来的?

粉丝提问,一口君必须满足

粉丝提问

二、解答

这个问题看上去很简单,但是要想把进程的父进程相关的所有知识点搞清楚,还是有点难度的,下面我们稍微拓展下,分几点来讲解这个知识点。

1. 如何查看进程ID

每个linux进程都一定有一个唯一的数字标识符,称为进程ID(process ID),进程ID总是一非负整数,它的父进程叫PPID。

查看进程ID命令:

ps -ef

查看进程

也可以使用函数来获得进程ID:

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); 返回:调用进程的进程ID
pid_t getppid(void); 返回:调用进程的父进程ID

2. 第一个进程init

Linux内核启动之后,会创建第一个用户级进程init,由上图可知, init 进程 (pid=1) 是除了 idle 进程 (pid=0,也就是 init_task) 之外另一个比较特殊的进程,它是 Linux 内核开始建立起进程概念时第一个通过 kernel_thread 产生的进程,其开始在内核态执行,然后通过一个系统调用,开始执行用户空间的 / sbin/init 程序。

3. fork函数

创建一个进程很简单,先来认识一下fork函数:

#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回:子进程中为0,父进程中为子进程I D,出错为-1

由fork创建的新进程被称为子进程( child process)。该函数被调用一次,但返回两次,两次返回的区别是子进程的返回值是0,而父进程的返回值则是子进程的进程ID。

一般来说,在f o r k之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法

「举例:」

#include <unistd.h>
int main()

pid_t pid;

if ((pid = fork()) == -1) {
perror("fork");
return -1;
} else if (pid == 0) {
this is child process
printf("The return value is %d In child process!! My PID is %d, My PPID is %d", pid,getpid(), getppid());

} else {
this is parent
printf("The return value is %d In parent process!! My PID is %d, My PPID is %d", pid,getpid(), getppid());

return 0;

执行结果:

fork

由上图可知,fork被调用了一次,返回了两次。

【拓展】

使用fork函数得到的子进程是父进程的处继承了整个进程的地址空间,包括:「进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端」等。

fork

fork出的子进程会集成父进程的文件描述符,如果读写文件,父子进程之间会互相影响。

4. ./run 运行的程序父进程是谁?

我们来编写一个例子:

int main(int argc, const char *argv[])

while(1);
return 0;

编译执行

gcc test.c
./a.out

例子很简单,就是创建一个死循环的进程。

ps -ef 查看进程ID

执行结果

由上图可知,a.out进程的进程ID是2991,父进程ID是2675,即进程bash:

2665

bash的父进程是gnome-terminal,所以大家应该明白,我们打开1个Linux终端,其实就是启动了1个gnome-terminal进程。我们在这个终端上执行./a.out其实就是利用gnome-terminal的子进程bash通过execve()将创建的子进程装入a.out:

strace

5. 进程和终端的关系

关于进程和终端的关系可以参考以下文章:

《进程组、会话、控制终端概念,如何创建守护进程?》

6. 父进程死了,子进程怎么办?

1) 僵尸进程

僵尸进程

如上图所示,

父进程Process A创建子进程Process B,当子进程退出时会给父进程发送信号SIGCHLD;如果父进程没有调用wait等待子进程结束,退出状态丢失,转换成僵死状态,子进程会变成一个僵尸进程。

当父进程调用wait,僵尸子进程的结束状态被提取出来,子进程被删除,并且wait函数立刻返回。

实例

#include <sys/types.h>
#include <unistd.h>
create a ZOMBIE
* ps -ax | grep a.out to show the zombie

int main()

if(fork()) {
//父进程
while(1){
sleep(1);


//子进程

上述程序会保证父进程不退出,一直在while(1)中无限循环,而子进程会立刻退出。

僵尸进程

由上图可知,父进程是3096,子进程是3097,子进程因为退出后父进程没有调用wait回收子进程资源,所以子进程3097变成僵尸进程defunct。

ps -ax | grep a.out 查看进程状态

僵尸进程

2) 孤儿进程

如果父进程退出,并且没有调用wait函数,它的子进程就变成孤儿进程,会被一个特殊进程继承,这就是init进程,init 进程会自动清理所有它继承的僵尸进程。

实例代码:

#include <sys/types.h>
#include <unistd.h>

int main()

if(fork()) {
//父进程

}else{
//子进程
while(1){
sleep(1);


上述程序会保证子进程不退出,一直在while(1)中无限循环,而父进程会立刻退出。

孤儿进程:

孤儿进程

./a.out的父进程ID变成1,所以该子进程被init进程继承。

三、其他启动进程的方法

1. exec族函数

fork函数用于创建一个子进程,该子进程几乎拷贝了父进程的全部内容。exec函数族提供了一种在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完之后,原调用进程的内容除了进程号外,其他全部都被替换了。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

每当进程调用一种exec函数时,该进程完全由新程序代换,而新程序从main函数开始执行。Exec并不创建新进程,所以前后进程ID也不会变。Exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。

「何时使用?」

当进程认为自己不能再为系统和用户做出任何贡献了时就可以调用exec函数,让自己执行新的程序如果某个进程想同时执行另一个程序,它就可以调用fork函数创建子进程,然后在子进程中调用任何一个exec函数。这样看起来就好像通过执行应用程序而产生了一个新进程一样。

「函数原型」

函数原型

2. cron命令

在Linux系统中,计划任务一般是由cron承担,我们可以把cron设置为开机时自动启动。cron启动后,它会读取它的所有配置文件(全局性配置文件/etc/crontab,以及每个用户的计划任务配置文件),然后cron会根据命令和执行时间来按时来调用度工作任务。

检查cron是否安装:

ps -ef | grep cron

croncrontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数
crontab -l //列出某个用户cron服务的详细内容
crontab -r //删除某个用户的cron服务
crontab -e //编辑某个用户的cron服务

root查看自己的cron设置:

crontab -u root -l

或者直接看自己名下的任务:

crontab -l

创建任务:

crontab -e

打开默认编辑器编辑后保存退出即可

编辑基本格式 :

*****command
分 时 日 月 周 命令
第1列表示分钟1~59 每分钟用*或者 1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
如果写为*, 表示每X
如果想定义间隔,在X后加"/"和间隔的数字

每隔一分钟打印一下系统时间

1 * * * * date >> ~/t.log //>> means append

3. at

在linux系统如果你想要让自己设计的备份程序可以自动在某个时间点开始在系统底下运行,而不需要手动来启动它,又该如何处置呢?

这些例行的工作可能又分为一次性定时工作与循环定时工作,在系统内又是哪些服务在负责?

还有,如果你想要每年在老婆的生日前一天就发出一封信件提醒自己不要忘记,linux系统下该怎么做呢?

但是crontab 主要用来提交不断循环执行的job, 而at 用来提交一段时间后执行的job(执行完就自动删除整个job)

「举例:」

1) 首先检查atd服务有无开启在一个指定的时间执行一个指定任务,只能执行一次,且需要开启atd进程

ps -ef | grep atd查看,
开启用/etc/init.d/atd start or restart;
开机即启动则需要运行 chkconfig --level 2345 atd on

2) 定时在11:30am用ls列出当前目录内容并写入~/log文件

cd ~
at 11:30am today
at>ls > ~/t.log
at> <EOT> //按Ctl-D退出

审核编辑:符乾江


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 进程
    +关注

    关注

    0

    文章

    203

    浏览量

    13960
  • Fork
    +关注

    关注

    0

    文章

    14

    浏览量

    3294
收藏 人收藏

    评论

    相关推荐

    深入解析Linux程序与进程

    什么是程序 一组计算机能识别和执行的指令,用于指导计算机执行特定任务或解决特定问题。程序通常由代码、数据和资源文件组成,涉及语法、算法和数据结构。为二进制文件 什么是进程 是一个具有独立功能的程序
    的头像 发表于 12-18 11:01 70次阅读
    深入解析Linux程序与<b class='flag-5'>进程</b>

    程序和进程的区别

    比如: 开发写的代码我们称为程序,那么将开发的代码运行起来。我们称为进程
    的头像 发表于 11-25 16:03 212次阅读
    程序和<b class='flag-5'>进程</b>的区别

    一文搞懂Linux进程的睡眠和唤醒

    优先级、文件描述符(记录当前进程打开的文件)、主要进程标识的进程号和进程号: 进程号(PID
    发表于 11-04 15:15

    Python中多线程和多进程的区别

    Python作为一种高级编程语言,提供了多种并发编程的方式,其中多线程与多进程是最常见的两种方式之一。在本文中,我们将探讨Python中多线程与多进程的概念、区别以及如何使用线程池与进程池来提高并发执行效率。
    的头像 发表于 10-23 11:48 392次阅读
    Python中多线程和多<b class='flag-5'>进程</b>的区别

    Linux用户身份与进程权限详解

    在学习 Linux 系统权限相关的主题时,我们首先关注的基本都是文件的 ugo 权限。ugo 权限信息是文件的属性,它指明了用户与文件之间的关系。但是真正操作文件的却是进程,也就是说用户所拥有的文件
    的头像 发表于 10-23 11:41 336次阅读
    Linux用户身份与<b class='flag-5'>进程</b>权限详解

    【软件干货】Android应用进程如何保活?

    在Android应用程序中,为了保证应用的正常运行和稳定性,有时需要对应用进程进行保活。以下是一些实现进程保活的方法:
    的头像 发表于 10-15 17:05 404次阅读
    【软件干货】Android应用<b class='flag-5'>进程</b>如何保活?

    深入探讨Linux的进程调度器

    Linux操作系统作为一个开源且广泛应用的操作系统,其内核设计包含了许多核心功能,而进程调度器(Scheduler)就是其中一个至关重要的模块。进程调度器负责决定在任何给定的时刻哪个进程可以运行
    的头像 发表于 08-13 13:36 939次阅读
    深入探讨Linux的<b class='flag-5'>进程</b>调度器

    鸿蒙开发:【进程模型】

    应用中(同一Bundle名称)的所有UIAbility、ServiceExtensionAbility和DataShareExtensionAbility均是运行在同一个独立进程(主进程)中,如下图中绿色部分的“Main Process”。
    的头像 发表于 06-13 09:53 277次阅读
    鸿蒙开发:【<b class='flag-5'>进程</b>模型】

    Linxu进程的延迟与周期调度

    pstree 命令以树状结构显示系统进程的继承关系。树状图将会以 pid (如果有指定) 或是以 init 为根,如果指定 user,则树状结构只显示该用户所拥有的进程
    发表于 04-18 11:24 179次阅读

    true studio调试,只显示汇编进程不显示C进程的原因?

    true studio 调试,只显示汇编进程,不显示C进程的原因?
    发表于 04-18 06:56

    进程间通信的消息队列介绍

    消息队列是一种非常常见的进程间通信方式。
    的头像 发表于 04-08 17:27 309次阅读

    HarmonyOS跨进程通信—IPC与RPC通信开发

    一、IPC与RPC通信概述 基本概念 IPC(Inter-Process Communication)与RPC(Remote Procedure Call)用于实现跨进程通信,不同的是前者
    的头像 发表于 02-02 17:47 1278次阅读
    HarmonyOS跨<b class='flag-5'>进程</b>通信—IPC与RPC通信开发

    浅谈Linux的进程

    进程和程序的区别: 进程是动态的,程序是静态的 一、进程的创建(fork()函数) int main(){ pid_t pid; pid=fork
    的头像 发表于 01-28 15:54 257次阅读
    浅谈Linux的<b class='flag-5'>进程</b>

    线程、进程、多线程、多进程和多任务之间有何关系?

    进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集。内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。
    的头像 发表于 01-11 13:39 358次阅读
    线程、<b class='flag-5'>进程</b>、多线程、多<b class='flag-5'>进程</b>和多任务之间有何关系?

    mcu线程和进程的区别是什么

    MCU线程和进程是嵌入式系统中常见的并行执行的概念,它们之间有许多区别,包括线程与进程的定义、资源管理、通信机制、执行方式等等。下面将详细介绍MCU线程和进程的区别。 一、定义与概念 MCU线程
    的头像 发表于 01-04 10:45 744次阅读