Linux 进程的一生

本文详细介绍了Linux系统中进程的创建与管理,包括使用fork函数创建子进程,通过if选择结构实现父子进程的不同操作,以及进程的终结和孤儿进程的处理。还探讨了子进程如何使用exec函数执行其他程序,以及wait函数在清理子进程资源中的作用。此外,提到了僵尸进程的问题及其对系统内存的影响。文章最后讨论了进程的生命周期和相关系统调用在实际编程中的应用。
摘要由CSDN通过智能技术生成

Linux进程的创建与管理

1、子进程的创建

查看进程命令 ps

$ps -eo pid,comm,cmd
-e 表示列出全部进程 
-o pid,comm,cmd表示我们需要PID,COMMAND,CMD信息

pid: 进程 id
command:进程名称
cmd:进程所对应的程序以及运行时所带的参数

注意:每个进程都有一个PPID(parent PID)来存储的父进程PID

//查询当下进程
[jyu@localhost Desktop]$ ps -o pid,ppid,cmd
  PID  PPID CMD
 2712  2710 /bin/bash
 2943  2712 ps -o pid,ppid,cmd

从中可以看出,第一个进程 是 第二个进程 的 父进程。

还可以用 pstree 命令来显示整个进程树

[jyu@localhost Desktop]$ pstree
init─┬─NetworkManager─┬─dhclient
     │                └─{NetworkManager}
     ├─abrtd
     ├─acpid
     ├─atd
     ├─auditd───{auditd}
     ├─bonobo-activati───{bonobo-activat}
     ├─clock-applet
     ├─console-kit-dae───63*[{console-kit-da}]
     ├─crond
     ├─cupsd
     ├─2*[dbus-daemon───{dbus-daemon}]
     ├─2*[dbus-launch]
     ├─devkit-power-da
     ├─gcalctool
     ├─gconfd-2
     ├─gdm-binary─┬─gdm-simple-slav─┬─Xorg
     │            │                 ├─gdm-session-wor─┬─gnome-

fork()通常作为一个函数被调用。这个函数会有两次返回,将子进程的PID返回给父进程,0返回给子进程。

系统调用 fork()
实际上,当计算机开机的时候,内核(kernel)只建立了一个init进程。Linux内核并不提供直接建立新进程的系统调用,剩下的所有进程都是init进程通过fork机制建立的。
父进程以分裂的方式来创建子进程,创建一个子进程的系统调用叫做fork()。

#include<stdio.h>

int main()
{
	int pid;
	int count1=0,count2=0;
	count1++,count2++;
	printf("count1=%d,count2=%d\n",count1,count2);

	pid=fork();
	count1++,count2++;
	printf("count1=%d,count2=%d\n",count1,count2);
	printf("pid=%d\n",pid);	

	return ;
}

[jyu@localhost Desktop]$ gcc process.c -o process
[jyu@localhost Desktop]$ ./process
count1=1,count2=1
count1=2,count2=2
pid=3047
[jyu@localhost Desktop]$ count1=2,count2=2
pid=0

2、进程的使用

通常在调用fork函数之后,程序会设计一个if选择结构。 当PID等于0时,说明该进程为子进程,那么让它执行某些指令。
比如说使用exec库函数(library function)读取另一个程序文件,并在当前的进程空间执行
(这实际上是我们使用fork的一大目的: 为某一程序创建进程); 而当PID为一个正整数时,说明为父进程,则执行另外一些指令。
由此,就可以在子进程建立之后,让它执行与父进程不同的功能。

#include <stdio.h>
#include <sys/types.h>
 
int main(void)
{
    pid_t pid;
 
    pid = fork();
    if(pid < 0){
        printf("error\n");               //打印fork()失败信息
    }else if(pid == 0){
        printf("I am subprocess\n");                //子进程代码
    }else{
        printf("I am parent process\n");                //父进程代码
    }
 
    return 0;
}
[jyu@localhost Desktop]$ gcc process.c -o process
[jyu@localhost Desktop]$ ./process
I am parent process
[jyu@localhost Desktop]$ I am subprocess

3、进程的终结

当子进程终结时,它会通知父进程,并清空自己所占据的内存,并在内核里留下自己的退出信息 (exitcode,如果顺利运行,为0;如果有错误或异常状况,为0的整数)。
在这个信息里,会解释该进程为什么退出。父进程在得知子进程终结时,有责任对该子进程使用 wait 系统调用。
这个wait函数能从内核中取出子进程的退出信息,并清空该信息在内核中所占据的空间。
但是,如果父进程早于子进程终结,子进程就会成为一个孤儿(orphand)进程。
孤儿进程会被过继给init进程,init进程也就成了该进程的父进程。init进程负责该子进程终结时调用wait函数。
当然,一个糟糕的程序也完全可能造成子进程的退出信息滞留在内核中的状况(父进程不对子进程调用wait函数),这样的情况下,子进程成为僵尸(zombie)进程。当大量僵尸进程积累时,内存空间会被挤占。

建设中

本文参考了以下两篇博客

https://blog.csdn.net/qq_38410730/article/details/81193118
另外是博客园的一篇博客,2012年,现在找不到了,题目好像是linux 进程基础

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值