没志青年
发布于 2025-06-14 / 17 阅读
0

[3] Linux 进程控制

启动进程

system

用于在代码中执行 shell 命令。

#include <stdlib.h>

int system(const char *command);

类型:库函数

线程安全:是

参数:

返回值:

  • 成功:

  • 失败:-1 并设置 errno

system 内部是调用 fork 来创建子进程,子进程来执行shell命令。

使用示例:

exec

用于执行一个程序,新程序会取代旧程序。

exec 有7个函数:

#include <unistd.h>

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


int execve(const char *pathname, char *const _Nullable argv[],
                  char *const _Nullable envp[]);

其中,只有 execve 为系统调用,其用函数都是在这上面封装的。

参数:

  • pathname:路径

  • file:文件名

  • arg:参数序列,使用,分隔

  • argv:参数列表

  • envp:环境变量列表

返回值:

  • 成功:不会返回,因为调用进程的实体(代码段、数据段、堆栈等)被新进程所取代了。

  • 失败:-1 并设置 errno

创建子进程

用于创建子进程。

fork

#include <unistd.h>

pid_t fork(void);

类型:系统调用

线程安全:是

参数:

返回值:

  • 成功:父进程中返回子进程 ID,子进程中返回 0

  • 失败:-1 并设置 errno

获取当前进程

父进程:

子进程:0

  • 父子进程共享代码段,不共享其它的。

  • 父子进程各从 fork 函数之后执行代码。

  • 子进程复制父进程的文件描述符,但不复制文件锁。

  • 子进程的未处理的闹钟定时器被清除,子进程不继承父进程的未决信号集。

vfork

#include <unistd.h>

pid_t vfork(void);

类型:系统调用

线程安全:是

参数:

返回值:

  • 成功:

  • 失败:-1 并设置 errno

fork 和 vfork 的区别

  1. fork 复制父进程的数据段,vfork 不完全复制。

阻塞父进程:

  1. fork 不阻塞父进程,所以运行顺序不确定。

  2. vfork 阻塞父进程(直到子进程退出或执行exec()),运行顺序确定,子进程先运行,父进程再运行。

使用场景:

  • fork:

  • vfork:

vfrok 的使用场景是调用exec的函数,

等待进程

类型:

线程安全:是

参数:

返回值:

  • 成功:返回

  • 失败:-1 并设置 errno

终止进程

类型:

线程安全:是

参数:

返回值:

  • 成功:

  • 失败:-1 并设置 errno

守护进程