linux系统进程概念以及相关函数(vfork、fork、exec)介绍

linux系统进程概念以及相关函数(vfork、fork、exec)介绍

进程的创建
  • fork之后,子进程共享父进程所有的文件描述符副本
    在这里插入图片描述

  • vfork()函数和fork()的区别:

    1. 子进程共享父进程的内存,直至成功执行exec()或者调用_exit()
    2. 子进程调用exec()或者_exit()之前,将暂停执行父进程
    3. 所以建议还是使用fork(),现在fork实现采用了写时赋值技术,这时候子进程只是简单的复制了进程地址空间中的用户空间部分,内核地址空间部分,子进程和父进程还是使用的相同的
  • fork之后,父、子进程谁先执行,两种行为之间的性能差异很小,对于大部分应用程序并无影响


进程的终止
  • _exit系统调用会直接终止进程,而exit是C语言标准库函数,会先调用进程退出处理程序,然后刷新stdio流,在调用__exit系统调用,return等同于exit

  • exit函数的参数(int status),虽然是int类型,但是实际只使用低8位,用返回给父进程,父进程通过wait之类的函数来获取status值

  • fork和stdio缓冲区的刷新:
    在这里插入图片描述

    1. 输出到终端的情况下,stdio流是行缓冲,所以输出结果是:

      • Hello word!
      • Ciao
    2. 因为是行缓冲,尽管printf把数据Hello word!存放在用户空间的标准IO的缓冲区中,当父进程执行printf的时候,因为有换行符所以立即刷新到内核缓冲区,然后执行write把数据Ciao刷新到内核缓冲区,然后fork的时候尽管会复制用户空间的标准IO的缓冲区,但是其中并没有内容了,所以子进程中执行exit也不会刷新任何内容到内核缓冲区

    3. 重定向输出到文件,输出结果

      • Ciao
      • Hello word!
      • Hello word!
    4. 因为是输出到文件,默认是全缓冲,父进程中printf把数据存放在用户空间的标准IO的缓冲区中,就算有换行符,也不会把数据刷新到内核缓冲区中,然后wirte把数据Ciao刷新到内核缓冲区,fork之后,子进程复制父进程的用户空间的标准IO的缓冲区,然后父进程和子进程,随机被CPU调用执行exit,然后刷新各自的用户空间的标准IO的缓冲区的内容Hello word!到内核缓冲区,所以才导致了如上的输出结果


监控子进程
  • 孤儿进程:子进程的父进程先退出的话,此时的子进程就变成了孤儿进程,孤儿进程一般会被ID号为1的众进程祖先init接管,此时在子进程中调用getppid就会返回1

  • 僵尸进程:子进程退出,但是父进程没有调用wait这类系统调用,然后子进程就会处于僵尸状态,等待父进程调用这类wait函数为其收尸

    1. 处于僵尸状态的子进程不能通过信号杀死,这样确保父进程可以调用wait来为其收尸
    2. 处于僵尸状态的子进程已经释放了大部分资源,唯一保留的是内核进程表中的一条记录,包括子进程ID,终止状态,资源使用数据
    3. 如果父进程没有给子进程收尸,就退出的话,init会自动接管僵尸进程,为其调用wait收尸
    4. 但是父进程如果一直不为僵尸子进程收尸,那么大量的僵尸子进程会占满内核进程表,导致新进程无法创建,所以应该及时为僵尸子进程收尸
    /****************************
    函数功能:截取路径中除去前面目录部分,最后面的文件或者路径名指针
    返回值:成功返回最后文件或者路径名的指针
    		失败返回NULL
    ****************************/
    #include <libgen.h>
    
    char *basename(char *path)
    /*举例
    basename("/tmp/dada"),返回指向dada的指针
    */
    

exec函数簇
  • exec函数之间的差异:
    在这里插入图片描述

    /***************************
    函数功能:根据环境变量,PATH,找到需要执行的可执行文件的位置,并执行相应可执行文件
    返回值:总是成功,失败返回-1
    ***************************/
    #include <unistd.h>
    int execlp(const char *file, const char *arg, ..., (char *)NULL)
    /*参数,采用列表的形式传递参数,而非数组的方式
    file:可执行文件名字
    从第二个参数开始,就是新的可执行文件的argv[0],argv[1]..............
    */
      
    /*程序举例*/
    int main(int argc ,char *argv[])
    {	
      		execlp("ls", "ls", "-l", "/tmp", (char *)NULL);			
      
      		return 0;
    }
    
    /*输出
    /tmp目录下文件和目录的详细信息
    */
    
    export PATH=/tmp //改变shell环境中,PATH的值为/tmp,终端关闭或者系统重新启动后,就会恢复到默认配置文件中的值
    echo $PATH       //输出环境变量PATH的值
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值