目录
- 结束进程
- 结束后台进程
- 结束前台进程
- 信号
- 基本概念
- 接收信号
- 发送信号
- 代码演示
- 接收信号函数(signal)
- SIG_IGN
- SIG_DFL
- 自定义函数
- 发送信号(kill)
- 接收信号解决僵尸进程
结束进程
结束后台进程
终端1:./main killed
终端2:ps -ef |grep “main” 该命令找到进程的PID,使用命令kill +进程号删除该进程。
结束前台进程
Ctrl + c :向终端发送一个信号 中断
信号
基本概念
接收信号
signal()函数
我们结束前台进程使用的Ctrl+c就是使用了信号进行强制退出。
信号是系统响应某个条件而产生的事件,进程接收到信号会执行相应的操作。
与信号有关的系统调用在“signal.h”头文件中有声明
信号的值在系统源码中的定义如下:
- #define SIGHUP 1
- #define SIGINT 2 //键盘按下 Ctrl+c 时,会产生该信号
- #define SIGQUIT 3
- #define SIGILL 4
- #define SIGTRAP 5
- #define SIGABRT 6
- #define SIGIOT 6
- #define SIGBUS 7
- #define SIGFPE 8
- #define SIGKILL 9 //该信号的响应方式不允许改变
- #define SIGUSR1 10
- #define SIGSEGV 11
- #define SIGUSR2 12
- #define SIGPIPE 13 //读端关闭的描述符,写端写入时产生,该信号会终止程序
- #define SIGALRM 14
- #define SIGTERM 15 //系统 kill 命令默认发送的信号
- #define SIGSTKFLT 16
- #define SIGCHLD 17 //子进程结束后,会默认给父进程发送该信号
- #define SIGCONT 18
- #define SIGSTOP 19
- #define SIGTSTP 20
- #define SIGTTIN 21
- #define SIGTTOU 22
- #define SIGURG 23
参数:
发送信号
kill()发送命令函数
kill() 可以向指定的进程发送指定的信号:
int kill(pid_t pid, int sig);
pid > 0 指定将信号发送个那个进程
pid == 0 信号被发送到和当前进程在同一个进程组的进程
pid == -1 将信号发送给系统上有权限发送的所有的进程
pid < -1 将信号发送给进程组 id 等于 pid 绝对值,并且有权限发送的所有的进程。 sig 指定发送信号的类型。
代码演示
接收信号函数(signal)
SIG_IGN
int main(){
signal(SIGINT,SIG_IGN);
while(1){
printf("main over!!\n");
sleep(2);
}
exit(0);
}
以上代码运行结果如下图,我们使用Ctrl+c无法进行退出,因为我们约定收到这个信号忽略这个信号。因此退出可以使用Ctrl+\。
SIG_DFL
int main(){
signal(SIGINT,SIG_DFL);
while(1){
printf("main over!!\n");
sleep(2);
}
exit(0);
}
SIG_DFL参数是约定按默认操作进行执行。使用Ctrl+c可以直接退出。
自定义函数
该函数我们是约定接收到命令之后调用fun函数使用,我们可以发现使用该函数,第一次接收到信号之后会执行输出命令,第二次接收命令之后会默认操作。
发送信号(kill)
int main(int argc,char* argv[]){
if(argc!=2){
printf("argc error\n");
exit(1);
}
//int pid=atoi(argv[1]);
int pid;
sscanf(argv[1],"%d",&pid);
if(kill(pid,SIGINT)==-1){
perror("kill error");
exit(1);
}
exit(0);
}
我们使用main函数的参数调用进程的PID作为参数,然后使用sscanf函数讲字符串转换为整型,调用kill函数时使用SIGINT参数是同Ctrl+c相同的信号,所以会直接退出。
以上代码我们也可以做一修改,将信号作为参数使用,进行改变,如下
执行结果:
接收信号解决僵尸进程
解决僵尸进程如下代码,使用的SIGCHLD参数是子进程结束会默认向父进程传递该信号,执行fun命令,wait(NULL)
执行结果如下:
该方法比较于直接在函数父进程的if条件下等待优点是不需要等待子进程运行结束之后才能运行父进程。同时运行,子进程结束会自动发送信号接收子进程的退出码来解决僵尸进程。