Linux的0,1,2号进程:
在Linux系统中,0、1、2号进程分别是`init`、`kthreadd`和`kswapd`。
-
0号进程(
init
):- 在早期的Linux版本中,0号进程是系统引导时由内核创建的第一个用户进程。
- 它是所有其他用户进程的祖先进程,也是系统中所有进程的根进程。
- 在现代Linux系统中,0号进程通常是
systemd
或init
进程的子进程,它负责启动和管理其他用户进程。
-
1号进程(
kthreadd
):- 1号进程是内核线程调度程序(Kernel Thread Daemon)的守护进程。
- 它是内核线程调度的主要负责者,负责创建和管理其他内核线程。
kthreadd
进程通常在内核初始化过程中被创建,并在系统运行期间一直存在。
-
2号进程(
kswapd
):- 2号进程是内核的交换守护进程(Swap Daemon)。
- 它负责将内存中不常用的页面(Page)移动到交换空间(Swap Space)中,以释放出物理内存供其他进程使用。
kswapd
进程通常在内核初始化过程中被创建,并在系统运行期间一直存在。
这些进程在内核启动过程中被创建,并且在整个系统运行期间一直存在,不同的Linux系统可能会有不同的进程号分配。它们的存在和正常运行对于系统的稳定性和功能是至关重要的。
进程标识:
在Linux系统中,每个进程都有一个唯一的进程标识符(Process Identifier),简称PID。PID是一个整数值,用于在系统中唯一标识一个进程。
进程标识符通常是一个非负整数,取值范围从2到32767。其中,0号进程和1号进程是特殊的系统进程,分别表示空闲进程和init进程。而2号进程则作为kthreadd进程存在。
进程标识符的分配是由内核进行管理的,在创建进程时由操作系统动态分配。每当创建一个新进程时,内核会为其分配一个未被使用的PID,并确保它在系统中的唯一性。如果一个进程终止,其所占用的PID将被释放,可以再次被其他新的进程使用。
PID在系统中的唯一性使得我们能够通过PID来识别、管理和操作不同的进程。可以使用命令如ps
、top
、kill
等来查看和控制进程,这些命令通常需要提供进程的PID作为参数。
fork()函数:
fork()
函数是一个用于创建新进程的系统调用函数。它的作用是复制当前进程,创建一个新的子进程,并且在父子进程之间返回不同的返回值。
调用fork()
函数后,操作系统会创建一个新的进程,该进程称为子进程,它是原始进程(父进程)的副本。子进程和父进程几乎完全相同,包括程序代码、变量、文件描述符和进程环境等。但是,子进程具有自己 ** 的进程标识符(PID),不同于父进程的PID。
fork()
函数有以下特点:
- 调用
fork()
函数后,父进程和子进程会继续执行接下来的指令。但是它们执行的上下文是不同的,因此可以通过返回值来区分父进程和子进程。 - 父进程中,
fork()
函数的返回值是子进程的PID,而在子进程中,fork()
函数的返回值是0。 - 如果
fork()
函数调用失败,返回值为-1,表示创建子进程失败。
一般情况下,我们可以通过检查fork()
函数的返回值来确定当前代码是在父进程还是子进程中执行。根据不同的返回值,可以编写不同的逻辑来实现父子进程的不同行为。
例如,以下是一个简单的示例代码,展示了fork()
函数的用法:
c
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
// 创建子进程失败
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程执行的代码
printf("我是子进程,我的PID是:%d\n", getpid());
} else {
// 父进程执行的代码
printf("我是父进程,我的PID是:%d,子进程的PID是:%d\n", getpid(), pid);
}
return 0;
}
运行以上代码,会创建一个子进程,并输出父子进程的不同信息。
fork()函数的两种用法:
共享文件:
当调用fork()函数创建子进程时,父进程的所有打开文件描述符都会被子进程继承。这意味着父进程和子进程可以通过它们各自的文件描述符来共享同一个文件。这种共享是通过操作系统的文件表来实现的。
在调用fork()函数后,子进程会得到与父进程相同的文件描述符表的副本。每个文件描述符都包含了指向打开文件的指针,这些指针指向操作系统内核中的文件表。因此,父进程和子进程实际上共享同一个文件表。
由于文件表是共享的,所以当父进程或子进程对文件进行读写操作时,它们实际上是在修改同一个文件表中的相应项。这样,父进程和子进程就可以通过文件描述符来实现对同一文件的协同操作。
需要注意的是,父进程和子进程共享文件描述符,并不意味着它们具有相同的文件偏移量。每个文件描述符都有自己的文件偏移量,这意味着父进程和子进程在读写文件时可能会出现互相干扰的情况。因此,在使用共享文件时,需要注意对文件偏移量的控制,以避免数据的混乱。
总结来说,通过fork()函数创建的父进程和子进程可以共享打开文件,但需要注意对文件偏移量的管理,以确保数据的一致性。