qidao123.com ToB IT社区-企服评测·应用市场

标题: 【Linux】进程 | 控制块pcb | task_struct | 创建子进程fork [打印本页]

作者: 耶耶耶耶耶    时间: 2026-2-27 09:04
标题: 【Linux】进程 | 控制块pcb | task_struct | 创建子进程fork
目次
Ⅰ. 进程的概念(Process)
1. 什么是进程?
2. 多进程管理
3. 进程控制块(PCB)
task_struct 的结构
Ⅱ. 进程查察与管理
1. 利用指令查察进程
​编辑
2. /proc 查察进程信息
​编辑
3. 获取进程 ID
4. 创建子进程
​编辑
缘故原由:fork()的 机制
总结
文章手稿:

xmind:

文章手稿可见文末 
 内容:明白“进程”的概念及其在利用体系中的管理,并探究进程控制块 (PCB) 的紧张性及其结构。本文还将先容怎样查察和管理进程,以及怎样通过体系调用创建进程。
Ⅰ. 进程的概念(Process)

1. 什么是进程?

进程是一个运行中的步调。当可实行文件被加载到内存中时,该步调就成为了一个进程。
2. 多进程管理

利用体系中大概同时存在大量的进程吗?of course
利用体系必要管理这些进程,以确保体系资源(如CPU时间、内存等)公道分配。管理进程的本质是对进程数据的管理。
   
  我们必要 先形貌再构造。(上一章我们讲过)
  以是,当一个步调加载到内存时,利用体系做的不但仅只是把代码和数据参加到内存,
  还要管理进程,创建对应的数据结构。
  Linux 利用体系的内核是 C 语言写的,形貌时就用到struct啦
  3. 进程控制块(PCB)

在利用体系中,用于形貌进程的结构体称为进程控制块(PCB)。在Linux中,这种结构体称为 task_struct。
task_struct 的结构

  1. struct task_struct {
  2.     volatile long state;
  3.     void *stack;
  4.     atomic_t usage;
  5.     unsigned int flags;     
  6.     unsigned int ptrace;
  7.     unsigned long ptrace_message;
  8.     siginfo_t *last_siginfo;
  9.     int lock_depth;         
  10.     // ... 其他属性
  11. };
复制代码
task_struct 包罗进程的全部属性数据,如进程状态、优先级、步调计数器、内存指针、上下文数据、I/O状态信息和记账信息等。
   利用体系对进程的管理,终极变成了对链表的增删查改。
  什么是进程?现在为止我们可以总结成:进程 = 可实行步调 + 该进程对应的内核数据结构
  利用体系不信赖托何人的,不会直接袒露自己的任何数据结构,代码逻辑,其他数据干系的细节。
想做体系是通过 体系调用 的方式,对外提供接口服务的。
下面我们未来学习一些体系接口

Ⅱ. 进程查察与管理

1. 利用指令查察进程


 运行

通过下面这些下令,可以方便地查察和管理体系中的进程。
指令寄义ps a表现现行终端机下的全部步调,包罗其他用户的步调ps -A表现全部步调ps c列出步调时,表现每个步调真正的指令名称ps -e表现全部步调ps e列出步调时,表现每个步调所利用的环境变量ps f用ASCII字符表现树状结构,表达步调间的相互关系ps -H表现树状结构,表现步调间的相互关系ps -N表现全部的步调,除了实行ps指令终端机下的步调之外ps s接纳步调信号的格式表现步调状态ps S列出步调时,包罗已停止的子步调资料ps -t <终端机编号>指定终端机编号,并列出该终端机的步调状态ps u以用户为主的格式来表现步调状态ps x表现全部步调,不以终端机来区分ps -l表现具体PID信息通过指令如 ps 和 top 可以查察体系中的进程信息。比方,利用 ps aux 可以表现体系中全部的进程:
  1. $ ps aux
复制代码

若需查察特定进程,可以利用 grep 过滤:
  1. $ ps aux
  2. | grep 'mytest' | grep -v grep
复制代码


相当于Windows 下的任务管理器:

2. /proc 查察进程信息

/proc 是一个假造文件体系,包罗当前体系的及时进程信息。
  1. $ ls /proc
复制代码


左边蓝色的就是pid
3. 获取进程 ID

每一个进程在体系中,都会存在一个惟一的标识符--pid

我们可以实行在proc 目次下找到这个 pid ,发现这个18705 目次

ctrl+c 可以发现进程具有及时性
 接下来我们重启来继承研究一下文件的创建和存储

 对代码举行一些改写
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main(void) {
  4.     FILE* fp = fopen("log.txt", "w");  // 若不存在就创建之
  5.     while (1) {
  6.         printf("I am m a process!\n");
  7.         sleep(1);
  8.     }
  9. }
复制代码


C语言专栏中讲到过,fopen 背面如果不带路径,那么会默认在当前路径。
所谓的当前路径,其本质 —— 当进步程所在的路径
进程会自己维护,进程会知道自己的工作路径在那里:
   


可以通过 getpid() 和 getppid() 体系调用获取当进步程和父进程的 ID。

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. int main(void) {
  5.     printf("PID: %d, PPID: %d\n", getpid(), getppid());
  6.     return 0;
  7. }
复制代码
运行可以看到:
 除了ctrl+c ,我们还可以这么制止进程
  1. $ kill -9 [pid]   # 给这个进程发送9号信号
复制代码

上面看到的ppid 我们也可以来测试一下
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. int main(void) {
  5.     while (1) {
  6.         printf("I am m a process! , pid: %d, ppid: %d\n",getpid(), getppid());
  7.         sleep(1);
  8.     }
  9. }
复制代码

4. 创建子进程

通过 fork() 体系调用可以创建子进程。fork() 有两个返回值:父进程返回子进程的 PID,子进程返回 0。

   为什么可以返回两个值呢? 
  我们可以来测试一下 
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. int main(void) {
  5.     pid_t id = fork();
  6.     if (id == 0) {
  7.         // 子进程
  8.         while (1) {
  9.             printf("我是子进程,我的pid: %d,我的父进程是 %d\n", getpid(), getppid());
  10.             sleep(1);
  11.         }
  12.     } else {
  13.         // 父进程
  14.         while (1) {
  15.             printf("我是父进程,我的pid: %d,我的父进程是 %d\n", getpid(), getppid());
  16.             sleep(1);
  17.         }
  18.     }
  19. }
复制代码


   缘故原由:fork()的 机制

  fork() 后,父进程和子进程会共享代码,数据则各自独立。通过差别的返回值,可以让父进程和子进程区分差别的实行流,实行差别的代码块。
  具体是怎么区分的可见文末手稿中的图解~ 
总结

进程是利用体系中非常紧张的概念。通过进程控制块(PCB)对进程举行形貌和管理是利用体系的一项紧张职责。通过利用各种工具和体系调用,我们可以方便地查察和管理进程,从而确保体系资源的有用利用。
文章手稿:


 

 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金




欢迎光临 qidao123.com ToB IT社区-企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.5