Linux环境编程 day05 进程

本文深入探讨了Linux环境下的进程管理,包括进程与程序的区别、进程查看方法、父进程与子进程的关系、孤儿进程和僵尸进程的概念。详细介绍了fork、vfork及exec系列函数在进程创建中的应用,以及进程的正常退出和异常终止。此外,还讨论了子进程的资源回收,如wait和waitpid函数的使用,确保系统资源的有效管理。

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

进程基本概念

进程与程序

    程序:就是存储在磁盘上的文件,里面包含了一些可以执行的二进制指令和数据。
    进程:就是运行着的程序(处于活动状态的程序)。

查看进程

    1、简单形式:ps 以简略形式显示当前用户控制的终端下的进程。
    2、以列表形式显示进程的详细信息:ps aux
        -a 所以用户控制的终端进程
        -u 以详细形式显示
        -x 包括无终端控制的进程
    3、进程详细信息表
        USER:进程属主
        PID:进程ID
        %CPU:CPU占用率
        %MEM:内存使用率
        VSZ:占用虚拟内存大小
        RSS:占用物理内存大小
        TTY:终端设备号,?表示无终端控制的进程
        STAT:进程的状态
            O 就绪状态,等待被调用
            R 运行状态,Linux系统没有O状态,就绪态也就是运行态。
            S 可被唤醒的睡眠状态,当系统中断、获得到资源、收到信号都可以反它唤醒然后转入运行状态。
            D 不唤醒的睡眠状态,只能被wake_up系统调用唤醒。
            T 暂停,收SIGSTOP(19)信号
            X 死亡状态
            Z 僵尸,已经停止,但父进程没有回收它的相关资源。
            s 会话首进程
            < 高优先级
            N 低优先级
            l 多线程化的进程
            + 在前台进程组中
        START:进程启动时间
        TIME:进程运行了多长时间
        COMMAND:启动进程的指令(可执行文件的名字)

父进程、子进程、孤儿进程、僵尸进程

    一个进程可以创建另一个进程,创建者叫父进程,被创建者叫子进程。
    当一进程的父进程先于子进程结束,子进程就变成了孤儿进程,孤儿进程会被收养到孤儿院(init)。有些版本的孤儿进程不会被收到孤儿院。
    当一个进程死亡时,它的父进程没有回收相关资源,此进程就变成了僵尸进程。

进程标识符

    每一个进程都有一个以非负整数表示的唯一编号,即进程PID。
    进程ID在任何时候都是唯一的,当可以重用,当进程结束时它的ID可以给新的进程用,采用的规则是延迟重用。
    #include <sys/types.h>
    #include <unistd.h>
    pid_t getpid(void);
    功能:获取当前进程的ID
    pid_t getppid(void);
    功能:获取父进程的ID

fork

#include <unistd.h>
pid_t fork(void);
功能:创建一个子进程
返回值:失败返回-1,成功返回两次
    父进程:返回子进程的pid
    子进程:返回0
    根据返回值的不同可以分别为父子进程编写不同的处理分支。

1、fork函数调用后父子进程各自运行,先后顺序不确定,但某些操作系统可以保证子进程先运行,父子进程谁先返回不确定。

2、子进程是父副本:子进程被创建时会拷贝父进程的data、bss、heap、stack、缓冲区等,唯独代码段不拷贝,父子进程共享一个代码段。


fork函数调用结束后,父进程的文件描述符,会复制到子进程中,此时子进程中也是可以继续该文件的,因为所有进程共享一个文件表(内核级)。
没有父子关系的两个进程,即使文件描述符相同,也不能共享访问同一个文件。

问题1:子进程是否会继承父进程的信号处理方式,实验证明。
    通过fork创建的子进程会继承父进程的信号处理方式。
问题2:子进程结束是是否会向父进程报告,父进程是否会有反应。
    子进程结束后内核会向父进程发送SIGCHLD信号,父进程默认的处理该信号方式是忽略,也可以进行捕获后回收子进程的资源。

总进程数是有限的,当进程过多超过系统限制,fork就会失败(不要轻易尝试,当fork失败前系统就已经卡的不行了)。

vfork

pid_t vfork(void);
功能:创建子进程

与fork的区别:
    1、子进程先返回,父进程等待,临时,需要子进程真正创建出来,然后父进程才返回。
    2、vfork无法单独创建出一个子进程,需要与exec函数配合。
    3、vfork不会复制父进程的相应数据内存,而是进行替换。

exec系列函数

这一系列函数的功能就是配合vfork创建子进程。
int execl(const char *path, const char *arg, ...);
path:程序的路径
arg:命令行参数(如果不给,就填一次和路径相同的字符串,不给了最后一个参数给NULL,下面的函数同理)

int execlp(const char *file, const char *arg, ...);
file:只需要程序的名字,系统会去PATH环境变量的路径中来查找这个程序。
arg:命令行参数

int execle(const char *path, const char *arg,..., char * const envp[]);
envp:环境变量表,创建子进程时传递父进程的环境变量表。

int execv(const char *path, char *const argv[]);
argv:命令参数以指针数组的形式提供

int execvp(const char *file, char *const argv[]);

int execvpe(const char *file, char *const argv[],
              char *const envp[]);

进程的正常退出

1、从main函数中return
2、调用标准库函数exit
    1、EXIT_SUCCESS/EXIT_FATLURE,约定好的进程的退出状态码,把参数的低8位返回给父进程。
    2、进程退出前会调用通过atexit/on_exit函数注册的函数。
    int atexit(void (*function)(void));
    功能:注册一个函数,当进程退出时调用此函数。
    int on_exit(void (*function)(int , void *), void *arg);
    功能:注册一个函数,当进程退出时调用此函数,同时可以附加一个指针参数(如果进程是通过return从main函数退出,则不能指向栈空间,因此此时栈空间可能已经被释放)。
    3、冲刷处理打开状态的标准IO流的缓冲区,并关闭文件。
    4、exit函数不会有返回,它之后的代码不会被执行。
    5、该函数的底层调用了系统的exit_group函数。
3、调用_Exit/_exit函数退出进程
   #include <unistd.h>
   void _exit(int status);  // 系统
   status: 0正常,-1不正常
   #include <stdlib.h>
   void _Exit(int status);  // 标准库
   功能:结束进程,这两个函数完全等价
    6、进程退出前会关闭处于打开状态的文件描述符。
    7、把所有的子进程托付给init进程(PID为的进程,也叫孤儿院),这个行为叫托孤。
    8、向父进程发送SIGCHLD信号。
4、进程的最后一个线程执行的返回语句。
5、进程的最后一个线程调用了pthread_exit函数。

进程的异常终止

1、进程收到某些信号,他杀。
2、进程自己调用abort函数,产生了SIGABRT信号,自杀。
3、进程的最后一个线程收到"取消"操作,并作出响应。

子进程的回收

pid_t wait(int *status);
功能:以阻塞状态等待子进程结束,并回收它的相关资源,只要有一个子进程结束它就返回,如果当前进程没有子进程就立即返回。
status:获取子进程的退出状态码,但只能获取到低8位。
    需要相关的宏进行解析才能获取到。
返回值:成功返回子进程的PID,失败返回-1。

pid_t waitpid(pid_t pid, int *status, int options);
功能:以阻塞状态等待子进程结束,与wait不同的是它可以指定等待哪个进程。
pid:要等待的子进程PID
    <-1 等待进程组中的任意子进程结束
    =-1 等待任意子进程结束,此时功能与wait等价。
    =0 等待同组的任意进程结束。
    >0 此时它代表着一个特定的子进程。
    
    
status:获取子进程的结束状态码, 需要相关的宏进行解析才能获取到。
options:
    0 表示忽略此参数,功能与wait一样。
    WNOHANG 如果没有子进程结束立即返回。
    WUNTRACED 如果有子进程暂停也立即返回
    WCONTINUED 如果有子进程从暂停状态切换为继续状态,立即返回。
返回值:成功返回子进程的PID,失败返回-1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值