1、ps和kill命令
ps和kill命令的格式
ps命令:
ps命令可以列出系统中当前运行的那些进程
命令格式:ps[参数]
命令功能:用来显示当前进程的状态
常用参数:aux
kill命令
kill命令用来杀死进程
eg: kill -9(SIGKILL) PID号
9号代表的是SIGKILL信号
2、关于ps命令
在ubuntu界面输入“ps a”,可以得到一下信息。“a”参数代表的是显示一个终端上的所有进程。
root@ubuntu:/home/topeet# cd
root@ubuntu:~# cd /home/samba/practice/
root@ubuntu:/home/samba/practice# ls
a.c a.out b.c c.c open.c practice2 practice2.c test
root@ubuntu:/home/samba/practice# ps a
PID TTY STAT TIME COMMAND
1010 tty7 Ssl+ 0:01 /usr/lib/xorg/Xorg -core :0 -seat seat0 -auth /var/r
1538 tty1 Ss+ 0:00 /sbin/agetty --noclear tty1 linux
2717 pts/18 Ss 0:00 bash
2798 pts/18 S 0:00 su root
2829 pts/18 S 0:00 bash
2877 pts/18 R+ 0:00 ps a
TTY | 当前的进程是要关联终端的,可以与我们进行交互 |
---|---|
STAT | 表示的是进程的状态,其中“z+”表示的是僵尸的 |
TIME | 表示进程的启动时间 |
COMMAND | 表示进程执行的具体的程序 |
注:< defunct >表示的是死掉了
“u”参数可以显示进程的归属用户以及相关的内存使用情况
VSZ | 表示进程使用的虚拟内存的大小 |
---|---|
RSS | 表示进程使用的虚拟内存的大小 |
%cpu | 表示进程占用了cpu计算能力的百分比 |
%MEM | 占用内存的百分比 |
“x”参数表示当前的进程是不关联终端的
如果要查看一个进程的相关信息,可以在ubuntu终端使用“ps aux”命令,但是这个命令执行之后显示的信息太多啦,如何快速找到想要找的进程呢?可以用“管道”来找。比如:要找到aux这个进程的相关信息,在终端键入该命令即可:
“|”表示的是管道的意思
root@ubuntu:/home/samba/practice# ps aux | grep aux
root 3614 0.0 0.0 39104 3248 pts/18 R+ 20:01 0:00 ps aux
root 3615 0.0 0.0 15984 944 pts/18 S+ 20:01 0:00 grep --color=auto aux
3、关于kill命令
使用“kill -l”查看ubuntu中kill命令都有哪些信号,可以看到9号为SIGKILL,故使用kill命令时,可以使用 “kill -9 PID号”来结束进程。
root@ubuntu:/home/samba/practice# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
在终端上执行可执行文件practice,再打开一个新的终端,查看practice的pid号,在新的终端上执行kill命令,原来的终端上会显示“已杀死”
4、孤儿进程、僵尸进程
孤儿进程 — 父进程结束以后,子进程还未结束,这个子进程就叫做孤儿进程。但是孤儿进程会被系统的init(pid号为1)进程所领养,此时它的父进程就变为了init进程。
僵尸进程 — 子进程结束以后,父进程还在运行,但是父进程不去释放进程控制块,这个子进程就叫做僵尸进程。
(1)关于孤儿进程的示例:
c代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
int i=0;
pid_t pid;
// 创建一个子进程
pid = fork();
if (pid < 0)
{
printf("fork is error \n");
return -1;
}
//父进程 让父进程先结束,并打印进程 PID
if (pid > 0)
{
printf("pid is %d\n", getpid());
}
//子进程,让子进程等待一会,让父进程先结束,并打印子进程的父进程的 pid
if (pid == 0)
{
sleep(2);
printf("parent pid is %d\n", getppid());
}
return 0;
}
在ubuntu上的编译结果如下所示:
由该编译结果可以看出,子进程中打印的父进程的进程号和父进程的进程号是不一样的,说明创建的子进程变成了孤儿进程,此进程被系统的 init 进程"领养"了。
重新打开一个终端查看一下这个pid号为1825的进程是谁?可以看到1825是upstart这样的一个进程 因为我们在这里使用的是一个带图形界面的ubuntu界面的图形系统 ubuntu系统使用默认的upstart作为默认的“领养”进程
(2)关于僵尸进程的示例
僵尸进程(子进程结束以后 还有一部分的资源需要释放 而这些资源必须要由父进程去释放)
c代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
int i=0;
pid_t pid;
// 创建一个子进程
pid = fork();
if (pid < 0)
{
printf("fork is error \n");
return -1;
}
//父进程
//让父进程先结束,并打印进程 PID
if (pid > 0)
{
while(1);
}
//子进程,让子进程先结束
if (pid == 0)
{
printf("This is child\n");
exit(0);
}
return 0;
}
在ubuntu上的编译结果如下所示:
重新打开一个新的进程,查看该可执行文件“practice”的状态,如下图所示:
5、wait()函数
(1)wait()函数是一个阻塞函数,它调用函数,只能回收一个进程。
Wait是阻塞函数,它会一直阻塞在那里直到子进程退出,wait函数会自动分析当前进程的某个子进程是否已经退出,如果有退出的子进程 wait函数就会自动收集子进程的信息,然后将其彻底销毁,这样就可以减少僵尸进程的产生。
头文件:#include <sys/wait.h>
函数原型:pid_t wait(int *status)
返回值:执行成功,则返回回收的子进程的pid,失败则返回-1
(2)与 wait 函数的参数有关的俩个宏定义:
WIFEXITED(status):如果子进程正常退出,则该宏定义为真
WEXITSTATUS(status):如果子进程正常退出,则该宏定义的值为子进程的退出值。
(3)wait函数示例
c代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
//用fork函数创建一个子进程
pid = fork();
//创建失败
if(pid < 0){
printf("error\n");
}
//父进程,让父进程一直运行,没有时间去释放进程控制块
if(pid > 0){
int status;
wait(&status);
if(WIFEXITED(status)==1){
printf("return value is %d\n",WEXITSTATUS(status));
}
//while(1); //这句如果取消注释,就会变成僵尸进程
}
//子进程,让子进程先结束
if(pid == 0){
sleep(2);
printf("This is child\n");
exit(0);
}
return 0;
}
在ubuntu终端编译的结果如下图所示:
最后打印的宏定义的值是子进程中的exit()函数中的值,此处是0,故打印值为0。若改为6 则打印值为6