1、回收资源空间:wait() 与 waitpid()

僵尸进程(Zombie Process):
    定义:进程退出后,其资源空间尚未被父进程回收的状态。
    特点:
        - 进程已终止,但仍在进程表中保留条目
        - 占用少量系统资源(如 PID),但不消耗 CPU 和内存
        - 无法被杀死,必须由父进程回收

如何避免僵尸进程产生?
    1. 父进程及时调用 wait() 或 waitpid() 回收子进程资源
    2. 让子进程成为孤儿进程(Orphan Process),由系统自动回收

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

 pid_t wait(int *wstatus);

 阻塞等待并回收任意一个已终止的子进程资源。
    该函数会暂停父进程,直到某个子进程结束。

参数:
    wstatus:指向整型变量的指针,用于保存子进程退出状态
             若不关心退出状态,可设为 NULL

返回值:
    成功:返回被回收的子进程的 PID
    失败:返回 -1(通常表示没有子进程或系统错误)

  wait(NULL);  // 不关心退出状态,仅回收子进程资源

2、 pid_t waitpid(pid_t pid, int *status, int options);   (了解)

        回收指定进程的资源。 与 wait 功能相似,但比 wait 更灵活,可以指定等待哪个子进程。

参数说明:pid:指定要等待的子进程 ID

                < -1:回收指定进程组内的任意子进程(例如:-100 表示等待 GID=100 的进程组中的任意子进程)

                = -1:回收任意子进程(不限于当前进程组)

                =  0:回收与当前调用 waitpid 的进程同属一个组的所有子进程

                 >  0:回收指定 PID 的子进程

status:指向整型变量的指针,用于保存子进程退出状态
            如果不关心退出状态,可设为 NULL

options:选项标志
        0:表示阻塞等待(默认)
        WNOHANG:非阻塞模式,若没有子进程退出则立即返回

返回值:
    成功:返回被回收的子进程的 PID
    失败:返回 -1
    若设置 WNOHANG 且无子进程可回收:返回 0

子进程资源空间回收策略

(1) wait 阻塞回收:父进程调用 wait() 阻塞等待子进程结束

(2)waitpid 非阻塞方式回收:使用 waitpid() 并设置 options 为 WNOHANG 实现非阻塞,父进程可在循环中轮询检查是否有子进程退出

(3)不回收:子进程任务需一直执行

(4)异步回收:使用信号机制(如 SIGCHLD)通知父进程子进程已结束

3、exec:函数族

在一个进程里面执行另外一个文件(可执行文件):
本质:将文本去的指令代码替换为 exec 要执行的文件的指令。

int execl(const char *path, const char *arg, ... /* (char *) NULL */);

参数:
    path:要执行的可执行文件的路径和名称
    arg:执行该可执行文件时需要传递的参数
    NULL:参数传递结束标志

返回值:
    出错:-1

int execlp(const char *file, const char *arg, ... /* (char *) NULL */);

功能:从 PATH 指定的系统路径下寻找该可执行文件

参数:
    file:需要执行的可执行文件的名称(系统路径下已有的文件)
    arg:执行该可执行文件时需要传递的参数

int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

4、线程:

(1) 什么是线程
   轻量级的进程,可实现多任务的并发。

  进程是操作系统资源分配的最小单位;
   线程是操作系统任务调度的最小单位。

(2)线程的创建
   线程由某个进程创建。
   进程创建线程时,会为其分配独立的(8M)栈区空间;
   线程和所在进程,以及进程中的其他线程,共用进程的堆区、数据区、文本区。

(3)线程的调度:宏观并行,微观串行

(4)线程消亡
   1. 线程退出
   2. 回收线程资源空间

(5)进程和线程的区别:

进程:
- 进程是操作系统资源分配的最小单位;
- 资源消耗:进程资源开销大,每次创建都需要有 0-4G 的虚拟内存空间;
- 效率角度:由操作系统创建,创建时耗时比线程大;跨进程调度比跨线程调度慢;
- 通信方面:进程间不能直接通信,需要使用进程间通信机制(IPC 机制);
- 安全性角度:进程安全性比线程高,各进程空间独立。

线程:
- 线程是操作系统任务调度的最小单位;
- 资源消耗:资源开销较小,只需要所在进程为其开辟 8M 的栈区空间;
- 效率角度:由所在进程创建;跨进程调度比跨线程调度慢;
- 通信方面:通信简单,可以使用线程共享的区域进行通信(比如全局变量);
- 安全性角度:线程没有进程安全性好,一个线程异常可能影响同一进程中的所有线程。

(6) 线程的相关编程

线程的创建:pthread_create()
   pthread_self():获取当前线程的ID号

 线程调度:由操作系统调度

线程消亡
   1. 线程退出:pthread_exit();
   2. 线程回收:pthread_join();

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);

参数:
    thread:保存线程ID的变量地址
    attr:线程属性的对象地址
         NULL:按照默认属性创建
    start_routine:函数的指针:指向线程启动后要执行的任务(线程任务函数)
    arg:为线程任务函数传递的参数

返回值
    成功:0
    失败:非0

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐