210120 阶段三 fork与阻塞函数

本文详细介绍了Linux中的fork函数及其对变量和文件描述符的影响,阐述了僵尸和孤儿进程的概念以及如何通过wait和waitpid避免僵尸进程。同时,讲解了execlp在子进程中的作用,以及如何创建和管理守护进程,包括setsid和文件描述符的关闭。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、学习的知识点

fork函数

fork函数产生两个进程,一个是主进程,也就是父进程,另一个是子进程。有两个返回值,一个返回值大于0,表示父进程,值为子进程的pid。一个返回值等于0,表示子进程。

变量的变化

fork以后,子进程对父进程 RW段(已初始化) BSS段(未初始化)的数据遵循写时拷贝,有改动时才执行拷贝,而RO段的数据是共用的

文件描述符的变化

fork前open的文件,fork后的子进程后父进程都有相同的文件描述符,但fork后open的文件只有执行open的进程才有对应的文件描述符。我的理解是文件描述符可以继承但不是共享的。

1.1僵尸状态

一个子进程结束运行时,父进程还存在

  1. 子进程进入僵尸状态,因为进程结束的返回码还需要给父进程 exit(0)
  2. 子进程不再活跃(不执行逻辑),但是资源无法释放(CPU/内存/数据)
  3. 以上总结说明 程序操作的时候不希望出现 僵尸状态的情况。

1.2孤儿

父进程先于子进程结束

  1. 父进程没了PID消失,父进程的所有子代进程都属于孤儿进程
  2. 父进程吧子进程托孤给系统管理
  3. 以上总结说明 程序操作的时候不希望出现。

1.3如何避免僵尸进程

1.3.1 wait

pid_t wait(int *status);
wait函数用于使父进程阻塞,只能让父进程等待子进程,不能使子进程等待父进程。
wait的返回值,如果等待成功 返回等待的pid号,出错则返回-1。
status参数 用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就象下面这样:pid = wait(NULL);
wait函数特点

  1. 如果有多个子进程在运行,那么wait函数只会等待先结束的子进程

1.3.2 waitpid

pid_t waitpid(pid_t pid, int * status, int options) ; 等待某个指定的子进程。等待进程ID为pid的进程

  • pid == -1 等待任一子进程。于是在这一功能方面waitpid与wait等效。
  • pid > 0 等待其进程I D与p i d相等的子进程。
  • pid == 0 等待其组I D等于调用进程的组I D的任一子进程。
  • pid < -1 等待其组I D等于p i d的绝对值的任一子进程。

2 execlp

在子进程里调用另外一个程序
execl系列函数的作用就是可以在你创建的子进程中调用其他人写好的可执行程序
execlp是替换进程映像 相关函数只要调用,后面的代码都不会执行 +p会导入系统的环境变量
execlp(“ls”, “ls -l”, NULL);
execlp(“ps”,“ps”,"-ax",0);

守护进程

概念:程序一旦启动就会转入后台,不会因为关闭终端而结束进程

  • 最重要的特性是后台运行
  • 如果你要脱离终端运行,首先要创建一个新的会话 创建会话函数 setsid();
  • 默认情况下 父进程不能创建会话
  • 创建的守护进程不要使用 printf、cout等输出函数。因为脱离终端 而字符输出依赖于终端 所以输出了也看不见
  • 在Linux中 输入输出都有设备 他有专门的文件描述符 0 1 2错误输出
  • 所以创建完守护进程后 也要分别关闭 close(0) close(1) close(2)
  • 在默认程序后
  • 一个终端可以运行很多进程 多个进程会组成会话 session 会话有权利创建终端
  • 一个进程可以产生子进程,产生多个子进程 为进程组 默认情况下父进程就是进程组组长
void create_deamons()
{
    pid_t pid = fork();
    if (pid == 0)
    {
        setsid();//因为父进程默认是进程组组长,所以不允许调用setsid函数来创建会话
        //子进程成功创建了会话,默认称为会话的领导者,这个会话领导者有一个权力:可以创建一个新的终端
        pid = fork();
        if (pid == 0)
        {
        //while循环要替换成守护进程的功能代码段
            while (1)
            {
                sleep(1);
            }
            //再创建一个子进程的时候,这个子进程不是会话组组长他就没有权力创建新的进程,真正脱离了终端运行
            //这里面的代码才是真正的守护进程代码
        }
        _exit(0);
    }
    else if (pid > 0)
    {
        _exit(0); //要写在父进程中 否则子进程会被杀死
    }
}

forint i =0;i<=2;i+{
close(i);
}
//关闭键盘 显示器 错误输出(并不是一定 一般规则如此)

二、上课没有听懂或者没有理解的地方

三、当天学习的收获

避免僵尸进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值