Linux系统编程 101 kill 函数和kill命令

信号的产生
终端按键产生的信号

Ctrl + c -> 2) SIGINT(终止/中断)   INT -Interrupt
Ctrl + z -> 20)SIGSTP(暂停/停止)   T  - Terminal
Ctrl + \ -> 3) SIGQUIT(退出)  

硬件异常产生信号
除0操作       -> 8) SIGFPE(浮点数异常)  
非法访问内存  -> 11)SIGSEGV(段错误)
总线错误      -> 7) SIGBUS

$cat kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    int a = 10;
    int b = a/0;
    return 0;
}
$gcc kill.c -o kill -Wall -g
kill.c: In function ‘main’:
kill.c:17:14: warning: division by zero [-Wdiv-by-zero]
     int b = a/0;
              ^
kill.c:17:9: warning: unused variable ‘b’ [-Wunused-variable]
     int b = a/0;
     
     
$./kill
Floating point exception (core dumped)


背后的东西是当前进程收到了SIGFPE 的信号


kill函数和kill命令

kill命令产生信号:kill  -SIGKILL PID

$cat kill_2.c 
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    int a = 10;
    while(1);
    return 0;
}
$gcc kill_2.c -o kill_2 -Wall -g
kill_2.c: In function ‘main’:
kill_2.c:16:6: warning: unused variable ‘a’ [-Wunused-variable]
  int a = 10;
$./kill_2  (然后会挂在那边)

在另外一个窗口中 查看PID

$ps aux |grep -i kill_
ubuntu     7779  100  0.0   4196   352 pts/8    R+   18:54   1:48 ./kill_2
ubuntu     7804  0.0  0.0  11752   932 pts/17   R+   18:56   0:00 grep --color=auto -i kill_
$kill -SIGKILL 7779
$./kill_2 
Killed

尝试段错误

$./kill_2  (然后会挂在那边)

另外一个终端:

$ps aux |grep -i kill_
ubuntu     7828  100  0.0   4196   352 pts/8    R+   18:57   0:22 ./kill_2
ubuntu     7834  0.0  0.0  11752   932 pts/17   R+   18:58   0:00 grep --color=auto -i kill_
$^C
$kill -SIGSEGV 7828


然后运行kill_2进程的终端显示的信息如下:

$./kill_2
Segmentation fault (core dumped)

尝试总线错误

$./kill_2  (然后会挂在那边)


在另外一个终端中输入:

$pkill -SIGBUS kill_2


然后运行kill_2进程的终端显示的信息如下:

$./kill_2
Bus error (core dumped)

关于manpage的使用的一些说明:
num    含义
1    在shell环境中可以直接操作的命令或者可运行文件
2    系统核心可以呼叫的函数或者工具
3    一些常见的函数与函数库,大部分为C的函数库
4    装置文件的说明,通常在/dev下的文件
5    配置文件或者是某些文件的格式
6    游戏
7    惯例与协议,Linux文件系统、网络协议、ASCII Code
8    系统管理员可用的管理命令
9    与Kernel相关的文件
kill函数

KILL(2)                    Linux Programmer's Manual                   KILL(2)

NAME
       kill - send signal to a process

SYNOPSIS
       #include <sys/types.h>
       #include <signal.h>

       int kill(pid_t pid, int sig);

第一个参数:进程ID
第二个参数:信号
返回值:成功是0  失败的时候 -1

说明:

PID> 0: 发送给指定的进程
PID =0: 发送信号给 与调用kill函数进程属于同一进程组的所有进程
PID<0 : 取|pid|发给对应的进程组
pid = -1: 发送给进程有权限发送的系统中的所有进程

进程组:每一个进程都属于一个进程组,进程组是一个或多个进程集合,他们相互关联,共同完成一个实体任务,
每一个进程组都有一个进程组长,默认进程组ID 和 进程组长ID 相同

权限保护:super用户

重点:
要记住,可以通过ps ajx 查看进程组ID.

$ps ajx
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
     0      1      1      1 ?            -1 Ss       0   0:02 /sbin/init


ps: process status 的缩写。ps命令列出系统中当前运行的哪些进程状态。
参数说明:
-A 显示所有进程(等价于-e)(utility)

-a 显示一个终端的所有进程,除了会话引线

-N 忽略选择。

-d 显示所有进程,但省略所有的会话引线(utility)

-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)

-p pid 进程使用cpu的时间

-u uid or username 选择有效的用户id或者是用户名

-g gid or groupname 显示组的所有进程。

U username 显示该用户下的所有进程,且显示各个命令的详细路径。如:ps U zhang;(utility)

-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.

-l 长格式(有F,wchan,C 等字段)

-j 作业格式

-o 用户自定义格式。

v 以虚拟存储器格式显示

s 以信号格式显示

-m 显示所有的线程

-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)

e 命令之后显示环境(如:ps -d e; ps -a e)(utility)

h 不显示第一行

signal 不推荐使用数字,应使用宏,因为不同操作系统信号信号编号可能不一样。
但其名称是一样的。


通过这个函数给指定的函数发送信号


小提示:
在程序中,如何查看函数的说明
将光标移动到函数;然后2+K

$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();//fork yi ge zijincheng
    if(pid > 0)
    {
        while(1)
        {
            printf("It's my parent process!,pid = %d\n",getpid());
            sleep(6);
        }
    }
    else if(pid == 0)
    {
        printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
        sleep(6);
        kill(getppid(),SIGSEGV);
      //  while(1);       
    }
    else
    {
    }
    return 0;
}
$gcc 101_kill.c -o 101_kill -Wall -g
$./101_kill 
It's my parent process!,pid = 13175
child process, pid = 13176,ppid = 13175
Segmentation fault (core dumped)

修改程序

$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();//fork yi ge zijincheng
    if(pid > 0)
    {
        while(1)
        {
            printf("It's my parent process!,pid = %d\n",getpid());
            sleep(6);
        }
    }
    else if(pid == 0)
    {
        printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
        sleep(6);
       // kill(getppid(),SIGSEGV);
        while(1);       
    }
    else
    {
    }
    return 0;
}
$./101_kill 
It's my parent process!,pid = 13293
child process, pid = 13294,ppid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293


在另外一个终端输入ps |ajx

 

13275  13293  13293  13275 pts/1     13293 S+    1000   0:00 ./101_kill
13293  13294  13293  13275 pts/1     13293 R+    1000   0:03 ./101_kill

修改程序,子进程向父进程发送SIGCHILD信号

$cat 101_kill.c 
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();//fork yi ge zijincheng
    if(pid > 0)
    {
        while(1)
        {
            printf("It's parent process!,pid = %d\n",getpid());
            sleep(6);
        }
    }
    else if(pid == 0)
    {
        printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
        sleep(6);
        kill(getppid(),SIGCHLD);
      //  while(1);       
    }
    else
    {
    }
    return 0;
}$cat 101_kill.c 
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();//fork yi ge zijincheng
    if(pid > 0)
    {
        while(1)
        {
            printf("It's parent process!,pid = %d\n",getpid());
            sleep(6);
        }
    }
    else if(pid == 0)
    {
        printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
        sleep(6);
        kill(getppid(),SIGCHLD);
      //  while(1);       
    }
    else
    {
    }
    return 0;
}
$./101_kill 
It's parent process!,pid = 14754
child process, pid = 14755,ppid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754


子进程向父进程发送SIGCHLD信号之后,
默认动作是忽略。父进程没有被终止。


kill 杀死进程组
修改程序:

$vi 101_kill.c
$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();//fork yi ge zijincheng
    if(pid > 0)
    {
        while(1)
        {
            printf("It's parent process!,pid = %d\n",getpid());
            sleep(6);
        }
    }
    else if(pid == 0)
    {
        while(1)
        {
            printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
            sleep(6);
            kill(getppid(),SIGCHLD);
             //  while(1);
        }       
    }
    else
    {
    }
    return 0;
}
$./101_kill 
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230


在另外一个窗口中

通过PID<0 : 取|pid|发给对应的进程组

$ps ajx |grep -i 101_kill
 14774  15435  15435  14774 pts/1     15435 S+    1000   0:00 ./101_kill
 15435  15436  15435  14774 pts/1     15435 S+    1000   0:00 ./101_kill
 15306  15440  15439  15306 pts/110   15439 S+    1000   0:00 grep --color=auto -i 101_kill

$kill -SIGKILL -15435
$ps ajx |grep -i 101_kill

 15306  15459  15458  15306 pts/110   15458 S+    1000   0:00 grep --color=auto -i 101_kill

PID =0: 发送信号给 与调用kill函数进程属于同一进程组的所有进程
这个只能在函数里面去做了。
修改程序:

$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();//fork yi ge zijincheng
    if(pid > 0)
    {
        while(1)
        {
            printf("It's parent process!,pid = %d\n",getpid());
            sleep(1);
        }
    }
    else if(pid == 0)
    {
        while(1)
        {
            printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
            sleep(6);
            kill(0,SIGKILL);
             //  while(1);
        }       
    }
    else
    {
    }
    return 0;
}
$gcc 101_kill.c -o 101_kill -Wall -g
$./101_kill
It's parent process!,pid = 15588
child process, pid = 15589,ppid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
Killed

$ps ajx |grep -i 101_kill
 15242  15627  15626  15242 pts/108   15626 S+    1000   0:00 grep --color=auto -i 101_kill


pid = -1: 发送给进程有权限发送的系统中的所有进程

kill -SIGKILL  -1
直接退到锁屏界面  然后拷贝功能(从乌班图拷贝到windows)之类的都无效。
重启一下就回复正常了

sudo init 6

权限保护: super用户root可以发送个任意用户,普通用户是不能先系统用户发送信号。
kill -9(root用户的pid)是不可以的。同样,普通用户也不能先其他普通用户发送信号,
终止其进程。只能向自己创建的进程发送信号。普通用户的基本规则:
发送者实际或有效用户ID == 接收者实际或者有效用户ID

sudo :super user do

$ps aux |more
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  4.6  0.0  34144  3388 ?        Ss   13:49   0:02 /sbin/init

进程ID 1是init 进程,这个进程是linux系统中所有的进程的祖宗。

$kill -9 1
bash: kill: (1) - Operation not permitted


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值