首页手机linux进程管理命令使用 linux进程管理基础知识

linux进程管理命令使用 linux进程管理基础知识

圆圆2025-07-09 12:00:51次浏览条评论

在前一篇文章中,我们已经对进程有了基本的认识,今天我们将继续探讨进程的实际操作——父子进程对文件的操作,以及什么是僵尸进程和孤儿进程?现在让我们揭开这些神秘的面纱!

一、父子进程对文件的操作:

1、子进程继承父进程中打开的文件:

父进程首先使用open函数打开一个文件并获取文件套接字(fd),然后通过fork函数创建子进程。之后,父子进程分别通过write函数向fd中写入内容,代码如下:#include lt;stdio.hgt;#include lt;sysgt;#include lt;fcntl.hgt;#include lt;unistd.hgt;#include lt;stdlib.hgt;int main() { //首先打开一个文件 int fd = -1; pid_t pid = -1; fd = open(quot;1.txt";, O_RDWR | O_TRUNC); if (fd lt; 0) { perror(quot;openquot;); exit(-1); } pid = fork(); if (pid gt; 0) { // 父进程中 printf(quot;parent.\nquot;); write(fd, quot;IOTNBquot;, 5); sleep(1); } else if (pid == 0) { // 子进程 printf(quot;child.\nquot;); write(fd, quot;MCUquot;, 3); sleep(1); } else { perror(quot;forkquot;); exit(-1); } close(fd); return 0;}登录后复制

输出结果:

Linux系统进程编程(二)

说明:我们可以看到,子进程继承了父进程中打开的文件,结果是接续写入(接续写入简单理解为在文件中继续写入内容)。需要注意的是,在实际测试中,有时可能只看到一个写入结果,这看起来像是分别写入,但实际上不是。因为父进程写入后立即关闭了文件,子进程就无法再写入内容。

2、父子进程各自独立打开同一个文件实现共享:

现在我们将文件操作分别放在父进程和子进程中,看看有什么效果,如下代码:#include lt;stdio.hgt;#include lt;sysgt;#include lt;fcntl.hgt;#include lt;unistd.hgt;#include lt;stdlib.hgt;int main(void) { //首先打开一个文件 int fd = -1; pid_t pid = -1; // fork创建子进程 pid = fork(); if (pid gt; 0) { // 父进程中 fd = open(quot;1.txtquot;, O_RDWR | O_TRUNC); if (fd lt; 0) { perror(quot;openquot;); exit(-1); } write(fd, quot;IOTNBquot;, 5);睡眠(1); close(fd); } else if (pid == 0) { // 子进程 fd = open(quot;1.txtquot;, O_RDWR | O_TRUNC); if (fd lt; 0) { perror(quot;openquot;); exit(-1); } write(fd, quot;MCUquot;, 3); sleep(1); close(fd); } else { perror(quot;forkquot;); exit(-1); } return 0;}登录后复制

输出结果:

Linux系统进程编程(二)

说明:最终结果是分别写入。原因是父子进程在分离后各自打开了1.txt,这两个进程的PCB已经独立,文件表也独立,因此两个读写器是完全独立的。当然,在打开文件操作时,可以通过改变open函数中的参数,使用O_APPE ND来实现接续写入。这里不再简单了,只需将上面的参数O_TRUNC改为O_APPEND即可。这两个参数的含义在之前的文章中已经详细介绍过。

3、小结:父进程在fork之前做的事情对子进程有很大,但在fork之后影响,父进程在自己的if语句块中所做的事情对子进程没有影响。本质原因是fork函数内部实际上已经复制了父进程的PCB,并生成了一个新的子进程,并且在fork返回时,子进程已经完全与父进程分离并由操作系统调度执行。

二、僵尸进程和孤儿进程解析:

1、什么是进程进程?

前面提到的进程进程可能会让人感到有点静止,但我们还是回到正题。在Linux系统中,我们需要理解:进程在运行时需要消耗系统资源(内存、I/O),当进程终止时,应该完全释放这些资源(进程如果终止后仍然没有释放相应的资源,这些资源就会丢失)。

因此,Linux系统设计时规定:每个进程退出时,操作系统会自动回收该进程涉及的所有资源(如malloc申请的内存没有free时,当前进程结束时这些内存会被释放,open打开的文件没有close时在程序终止时也被关闭)。但是,操作系统只恢复了process工作时占用的内存和I/O,而没有回收进程本身占用的内存(8KB,主要是task_struct和栈内存),因为进程本身的8KB内存需要由其他进程来辅助回收。因此,每个进程都需要一个帮助其“收尸”的人,这个角色就是其父进程。所以,僵尸进程是指——子进程先于父进程结束。子进程结束后,父进程立即不一定能够帮其“收尸”,在这段时间内(子进程已经结束且父进程尚未)帮其收尸),子进程就被称为僵尸进度。下面我们看一个演示:#includelt;stdio.hgt;#includelt;unistd.hgt;#includelt;stdlib.hgt;#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)int main() { pid_t pid; if((pid = fork()) == -1) ERR_EXIT(quot;forkquot;); else if (pid == 0) { printf(quot;我是孩子,我的pid : d,我爸爸的pid : d!\nquot;,getpid(),getppid()); } else { while(1) { printf(quot;我是爸爸,我的pid : d!\nquot;,getpid()); sleep(2); } } return 0;}登录后复制

输出结果:

Linux系统进程编程(二)

2、什么是孤儿进程?

子进程死亡需要父进程来处理,这意味着正常的进程应该是子进程先于父进程死亡。当父进程先于子进程死亡时,子进程死亡时没有父进程处理,这个死亡的子进程就是孤儿进程。同时,Linux系统规定:所有孤儿进程都自动成为一个特殊进程(进程1,在init进程之前)的子进程。

下面我来演示一下:#include lt;stdio.hgt;#include lt;sysgt;#include lt;unistd.hgt;int main(void) { pid_t p1 = -1; p1 = fork(); // 返回2次 if (p1 == 0) { // 这里一定是子进程 // 先sleep一下让父进程先运行,先死 sleep(1); printf(quot;子进程, pid = d.\nquot;, getpid()); printf(quot;hello world.\nquot;); printf(quot;子进程,父进程ID = d.\nquot;, getppid()); } if (p1 gt; 0) { // 这里一定是父进程 printf(quot;父进程, pid = d.\nquot;, getpid()); printf(quot;父进程, p1 = d.\nquot;, p1); } if (p1 lt; 0) { perror(quot;forkquot;); exit(-1); } return 0;}登录后复制

输出结果:

Linux系统进程编程(二)

说明:这里父进程先运行并死亡,但是后面我们并没有发现特殊进程init的进程ID为1,而908,这其实和Ubuntu系统有关,实际应为1。

三、总结:

后续还会继续更新有关进程的文章,今天的学习加深了对进程的进一步理解,后面会介绍回收进程的具体实现方法。

以上就是Linux系统进程编程(二)的详细内容,更多请关注乐哥常识网文章相关其他!

Linux系统进程编
迷雾怪物图鉴 迷雾大怪
相关内容
发表评论

游客 回复需填写必要信息