在Linux中,有多种方法可以创建新进程
- fork()系统调用:fork()系统调用是创建新进程的最常用方法。它创建一个与当前进程几乎完全相同的子进程。子进程从父进程那里继承代码、数据、堆栈、文件描述符等。子进程的执行从fork()返回处开始。在父进程中,fork()返回子进程的进程ID(pid),在子进程中,fork()返回0。通过检查fork()的返回值,可以区分父进程和子进程。
示例代码:
#include#include #include #include #include int main() { pid_t pid = fork(); if (pid < 0) { perror("fork error"); exit(EXIT_FAILURE); } if (pid == 0) { // 子进程 printf("I am the child process, my pid is %d\n", getpid()); } else { // 父进程 printf("I am the parent process, my pid is %d\n", getpid()); printf("My child process's pid is %d\n", pid); } return 0; }
- exec()系列系统调用:exec()系列系统调用用于在当前进程的上下文中替换一个新的程序。这将导致当前进程的代码、数据、堆栈和文件描述符被新程序的相应部分替换。一旦执行exec(),之前的进程就不存在了。exec()系列函数有以下几种形式:
- execl():加载一个新程序并替换当前进程的映像。
- execv():加载一个新程序并替换当前进程的映像,参数以数组形式传递。
- execle():加载一个新程序并替换当前进程的映像,同时设置环境变量。
- execve():加载一个新程序并替换当前进程的映像,参数和环境变量以数组形式传递。
- execlp():在系统的PATH环境变量中查找可执行文件,然后加载并替换当前进程的映像。
- execvp():在系统的PATH环境变量中查找可执行文件,然后加载并替换当前进程的映像,参数以数组形式传递。
- fork()和exec()的组合:通常,我们首先使用fork()创建一个子进程,然后在子进程中使用exec()系列函数执行新的程序。这样,我们可以在新程序中运行代码,同时保留父进程的状态和信息。
示例代码:
#include#include #include #include #include int main() { pid_t pid = fork(); if (pid < 0) { perror("fork error"); exit(EXIT_FAILURE); } if (pid == 0) { // 子进程 char *argv[] = {"ls", "-l", NULL}; execvp(argv[0], argv); perror("execvp error"); exit(EXIT_FAILURE); } else { // 父进程 int status; waitpid(pid, &status, 0); printf("Child process exited with status %d\n", WEXITSTATUS(status)); } return 0; }
这个示例中,父进程使用fork()创建一个子进程,然后在子进程中使用execvp()执行ls -l
命令。父进程等待子进程结束,并打印子进程的退出状态。