1. 创建进程的概念
在Linux系统中,进程是执行中的程序的实例。每个进程都有自己的地址空间、代码、数据和打开的文件等。进程是通过fork()系统调用创建的,通过创建子进程来执行新的进程。
创建进程的步骤如下:
2. 子进程的创建(fork())
使用fork()系统调用可以创建一个新的进程。fork()函数会复制当前进程的所有内容,包括代码、数据和文件等。新的进程被称为子进程,原来的进程称为父进程。
在创建子进程时,fork()函数返回两次。对于父进程来说,fork()返回子进程的PID;对于子进程来说,fork()返回0。这样就可以通过返回值来区分父进程和子进程。
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed\n");
return 1;
}
else if (pid == 0) {
// 子进程
printf("This is child process\n");
}
else {
// 父进程
printf("This is parent process\n");
}
return 0;
}
2.1 子进程的创建过程
子进程的创建过程发生在fork()函数调用之后。在调用fork()之前,父进程的空间中的所有内容都会被复制到子进程的空间中。这包括代码、数据和打开的文件等。
子进程的代码从fork()调用的位置开始执行。子进程的执行上下文和父进程一样,只是fork()函数调用返回的值不同。
3. 父子进程的区分
父进程和子进程的PID不同,可以通过这一特性来区分父子进程。在上面的例子中,使用了PID的值来区分父进程和子进程,并打印相应的信息。
另外,父进程和子进程的返回值也不同。在父进程中,fork()返回子进程的PID;在子进程中,fork()返回0。可以根据返回值来判断当前进程是父进程还是子进程。
3.1 子进程执行的代码
else if (pid == 0) {
// 子进程
printf("This is child process\n");
}
在子进程中,可以执行与父进程不同的代码。在上面的例子中,子进程打印了一个信息来区分与父进程的不同。
3.2 父进程执行的代码
else {
// 父进程
printf("This is parent process\n");
}
在父进程中,同样可以执行与子进程不同的代码。在上面的例子中,父进程也打印了一个信息来区分与子进程的不同。
4. 父子进程的执行顺序
在使用fork()创建子进程后,父子进程的执行顺序是不确定的。操作系统会根据调度算法来决定哪个进程先执行,无法预测。
如果希望子进程在父进程之前执行,可以使用wait()系统调用。wait()可以使父进程阻塞,直到子进程执行完毕。
下面的代码演示了如何使用wait()来等待子进程的结束:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid;
int status;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed\n");
return 1;
}
else if (pid == 0) {
// 子进程
printf("This is child process\n");
exit(0);
}
else {
// 父进程
wait(&status);
printf("Child process finished\n");
}
return 0;
}
通过调用wait()函数,父进程会等待子进程执行完毕。在子进程中,调用exit()函数可以使子进程结束并返回给父进程一个可以判断子进程是否正常终止的状态。
4.1 子进程执行的代码
else if (pid == 0) {
// 子进程
printf("This is child process\n");
exit(0);
}
在子进程中,可以使用exit()函数来结束子进程的执行。exit()函数的参数表示子进程的状态,可以用于告诉父进程子进程的执行结果。
4.2 父进程执行的代码
else {
// 父进程
wait(&status);
printf("Child process finished\n");
}
在父进程中,调用wait()函数来等待子进程的结束。wait()函数的参数是一个指向整型变量的指针,用于存储子进程的返回状态。
5. 总结
通过上述步骤,可以在Linux系统下创建一个新的进程。使用fork()系统调用可以创建子进程,通过返回值来区分父进程和子进程。父进程和子进程可以执行不同的代码,并且可以使用wait()函数等待子进程的结束。
有了这些基础的步骤,我们可以在Linux系统中灵活地管理进程,实现更复杂的功能。