Linux进程常用项总结(进程管理函数、命令行批量kill)

进程:

1.进程和程序的区别:

程序是放在磁盘上的可执行文件,而进程是程序的执行状态。进程除了有自己的存储空间外,还有包括程序计数器、寄存器和当前值,拥有独立的处理环境和系统资源,可以这么说,进程是资源分配和事务管理的单位,它们拥有独立的资源。

2.进程的状态与转换:

简单的三种状态:运行态、就绪态、阻塞态。

linux进程的七种状态:(1、2、3、4)可认为是阻塞态。

Linux进程常用项总结(进程管理函数、命令行批量kill)_第1张图片

有关进程控制的函数

头文件一般需要有(sys/types.h unistd.h sys/time.h stdlib.h)

一、查看进程号:pid_t即int类型,命令行下可以用ps命令检验。

1.pid_t getpid(void) 获取本进程号;

2.pid_t getppid(void) 获取本进程的父进程号;

3.pid_t getpgpid(pid_t pid) 获取pid的进程组号,为0时返回本进程的进程组号;

二、启动新的进程:

1.system函数调用:

int system(const char *command)  该函数是由stdlib.h提供的库函数,通过调用/bin/sh 来执行comman命令。以来shell以及环境,效率不高;执行完之后可以发现command的父进程为bash,bash就是linux的sh命令解析器。

2.进程替换:exec函数(相当于原进程被自己杀死,然后产生一个新进程执行函数第一个参数,后面带参数)

int execve(const char *file, char *const argv[], char *envp[])  该函数是内核提供的接口,以下函数在此基础上封装而成。其中参数file需带完整路径或已经在环境变量path里的可执行文件、argv是命令参数(注意命令本身是第一个参数)、e表示参数envp可指定环境变量。v的意思是已经定义了一个字符数组,参数存在了字符指针数组内,可直接传入指针数组使用

int execl(const char *path, char *arg, ..., (char *) 0); 注意最后一个参数必须是(char *)0,下面的函数也是。第一个参数需带完整路径;

int execlp(const char *file, char *arg, ..., (char *) 0); 这个函数名比上面那个多了一个p,意思是第一个参数路径为环境变量path,无需完整路径。

以上三个参数比较常用,可以组合出exec(ve、v、vp、l、lp、le)六个函数。

3.进程复制:

①、pid_t fork(void) 该函数在执行后产生一个子进程,最初调用了fork的称为该子进程的父进程。子进程会复制父进程,然后执行fork函数后面的代码。在上面两种产生新的进程的方法都是只能让进程执行已经存在的某份可执行文件,在这里可以让进程继续执行。

在父进程中该函数返回的是新产生子进程的进程号,而子进程中返回的是0,我们依靠函数返回值判断该进程是父进程还是子进程。产生一个子进程一般是想让它干和父进程不同的事。比如自制MP3播放器时想让一个进程负责播放,一个负责显示歌词。可以用下面代码逻辑。

int main(int argc,char *argv[])
{
	pid_t pid=-1;
	pid=fork();
	if(pid<0)
	{
		//fork erro
	}
	else if(pid==0)
	{
		//子进程负责播放歌曲 
	}else
	{
		//父进程负责显示歌词 
	}
	return 0; 
}
fork还会涉及到僵尸进程等问题,在另一篇文章记录。 fork函数的总结(还没写,链接现在是baidu)

②、pid_t vfork(void) 该函数和fork类似,不同的是fork产生子进程和父进程执行顺序是不确定的,而vfork保证了子进程先执行,子进程退出后父进程才执行。并且子进程刚被创建的时候并不像fork一样分配一片新的进程空间,而是在父进程的空间里执行。由这样的特性可以看出来vfork设计出来就是为了和exec函数配合使用的,即子进程一被创建出来就使用exec函数替换掉自己,这时会分配一块新的进程空间给子进程。

三、进程阻塞:

1.进程挂起:

unsigned int sleep(unsigned int sec)和unsigned int usleep(unsigned int usec)分别是挂起sec秒和sec微秒,不过Linux调度是毫秒级的,所以usleep不怎么准确。并且sleep结束后被挂起的进程并不一定能得到马上执行,还是要先切换到就绪态等待CPU。

2.进程等待:

①、pid_t wait (int*status) 该函数使调用该函数的进程等待子进程结束,如果子进程结束,该函数会回收子进程的资源。子进程未结束则会将父进程挂起,直到子进程退出,如果该进程没有子进程在运行则会立即退出。status参数可以记录子进程退出时的状态信息。

②、pid_t waitpid(pid_t pid, int *status, int options) 该函数有点想wait的扩展版,功能是和wait一样的,区别主要在参数。

参数:pid pid>0:等待进程ID为pid的子进程;

pid=0:等待同一进程组中的任何子进程,如果有子进程已经加入别的进程组,那就不会等待它

pid=-1:等待任一子进程,此时和wait作用一样;

pid<-1:等待绝对值为pid的进程组中的任一子进程;

参数:status 和wait中的一样

参数:options 0:和wait一样,阻塞父进程等待子进程;

WNOHANG :没有子进程结束时不阻塞父进程(其他不常用)

四、进程退出:

1.void exit(int value) value为0表示正常退出,非0表示非正常退出,一般会有对应情况;

2.void _exit(int value)  和exit类似,与它的区别是exit为库函数,_exit为系统调用。并且exit退出时会做一些处理动作,而_exit则是直接退出了进程

return 和exit 的区别是exit是停止进程并且value表示进程退出状态,return是函数返回的标识可以返回多种数据类型。

批量杀死进程:

现在有这种情况:有一个函数fork一堆僵尸进程,如果要等init进程回收会很慢,想要手动kill这些进程,但是又因为进程数量太多手动操作麻烦。可以采用下面这种操作。

命令:ps -efww|grep sleep_sort|grep -v grep|cut -c 9-15|xargs kill -9

可以看出来这是很多个命令通过管道串联起来的一个组合命令。管道可以把左边的输出转换为右边命令的输入。解析一下这个命令:

ps -efww 是查看所有活动的进程;

grep sleep_sort 是取出所有包含sleep_sort的行,sleep_sort即需要杀死的进程名称;

grep -v grep 是排除包含grep的行,grep也是个进程;

cut -c 9-15 是将一行中第9到15个字符裁下来,通过ps -e可以看出这几个字符就是进程ID号所在的位置;

xargs kill -9 是执行kill命令,xargs表示接收管道传入信息作为输入信息,-9表示强制杀死。

你可能感兴趣的:(Linux系统编程)