c(5)进程的信号处理

1)信号处理
捕获信号
//sig.c
输出:
^C

3811进程:收到2信号

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
//定义信号处理函数
void sigint(int signum){
	printf("\n%d进程:收到%d信号\n",getpid(),signum);
}
int main(){//当有中断符信号SIGINT出现时,调用指定的函数sigint
	if(signal(SIGINT,sigint)==SIG_ERR){
		perror("signal");
		exit(EXIT_FAILURE);
	}
	sleep(10);//睡眠10秒,期间等待用户按下Ctrl+C以收到信号
	return 0;
}

fork/vfork函数创建的子进程会继承父进程的信号处理方式,直到子进程调用exec函数创建新进程替代其自身。
exec函数创建的新进程会将原进程中被设置为捕获的信号还原为默认操作,毕竟位于原进程地址空间中的信号处理函数,此时已经被新进程的地址空间完全取代了。
信号处理的继承
//02siginherit.c
输出:
这是父进程,pid=4179
这是子进程,pid=4180父进程的pid=4179
^C

-341902544进程,收到-341902848信号-341902544进程,收到-341902848信号
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
//定义信号处理函数sigint 
void sigint(int signum){
	printf("\n%d进程,收到%d信号");
}
int main(){//使用函数signal设置针对中断符信号的处理方式
    //当有中断符信号出现时,调用法指定的函数sigint
	if(signal(SIGINT,sigint)==SIG_ERR){
		perror("signal");
		exit(EXIT_FAILURE);
	}
	pid_t pid;
	if((pid=fork())<0)
	    perror("fork");
	else if(pid==0){
		printf("这是子进程,pid=%d",getpid());
		printf("父进程的pid=%d\n",getppid());
	}
	else
	    printf("这是父进程,pid=%d\n",getpid());
	sleep(10);
	return 0;
}

信号处理的恢复

//02sigexec.c
输出:

execl: No such file or directory

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
void sigint(int signum){
	printf("\n%d进程:收到%d信号\n",getpid(),signum);
}
int main(void){
	if(signal(SIGINT,sigint)==SIG_ERR){
		perror("signal");
		exit(EXIT_FAILURE);
	}
	if(execl("foo","foo",NULL)==-1){
		perror("execl");
		exit(EXIT_FAILURE);
	}
	sleep(10);
	return 0;
}


2)
杀死进程
在子进程中杀死父进程
//03kill.c
输出:
这是父进程,pid=2364
这是子进程,pid=2365,父进程的pid=2365
按回车键,终止父进程

^C[按回车没反应,不知原因]
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
int main(){
	pid_t pid;
	if((pid=fork())<0){
		perror("fork");
	}
	else if(pid==0){
		printf("这是子进程,pid=%d,",getpid());
		printf("父进程的pid=%d\n",getpid());
		printf("按回车键,终止父进程\n");
		getchar();//子进程中等待按回车键
		kill(getpid(),SIGTERM);/*等到后使用kill函数向父进程
		发送SIGTERM信号,杀死父进程*/
	}
	else{
		printf("这是父进程,pid=%d\n",getpid());
		while(1)//进入死循环,等到子进程将其杀死
			pause();
	}
	return 0;
}


进程自杀

<signal.h>
int raise(int sig);
//03raise.c
输出:
按回车键,终止进程

已终止
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
	printf("按回车键,终止进程\n");
	getchar();//等待回车被按下
	raise(SIGTERM);//等到后使用raise函数向自身发送退出符SIGTERM信号,终止进程
	while(1)
	    pause();//若没有raise函数,将进入死循环
	return 0;
}

3)
暂停
<unistd.h>
int pause(void);
使用函数pause使当前进程无限睡眠,当有信号被当前进程捕获,当信号处理函数返回以后,pause函数返回,返回值为-1,同时置errno为SIG_ERR,表示阻塞的系统调用被信号中段。pause函数要么不返回,要么返回失败,不会返回成功。
//04pause.c
输出:
按Ctrl+C继续
^C
中断符信号被发送

进程继续

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
void sigint(int signum){
	printf("\n中断符信号被发送\n");
}
int main(){
	if(signal(SIGINT,sigint)==SIG_ERR){
		perror("signal");
		exit(EXIT_FAILURE);
	}	
	printf("按Ctrl+C继续\n");
	if(pause()==-1 && errno!=EINTR){
		perror("pause");
		exit(EXIT_FAILURE);
	}
	printf("进程继续\n");
	return 0;
}

睡眠
<unistd.h>
unsigned int sleep(unsigned int seconds);
使用函数sleep使当前进程睡眠60秒,除非用户按下Ctrl+C发送中断信号被其捕获,如果有信号被调用进程捕获,在信号处理函数返回以后,sleep函数才会返回,且返回值为剩余的秒数,否则该函数将返回0,表示睡眠充足。
//04sleep.c
输出:
按Ctrl+C继续,或等待进程睡足1分钟。
^C
中断符信号被发送
进程被提前57秒叫醒

进程继续

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
void sigint(int signum){
	printf("\n中断符信号被发送\n");
}
int main(void){
	if(signal(SIGINT,sigint)==SIG_ERR){
		perror("signal");
		exit(EXIT_FAILURE);
	}
	printf("按Ctrl+C继续,或等待进程睡足1分钟。\n");
	int alarm=sleep(60);
	if(alarm)
	    printf("进程被提前%d秒叫醒\n",alarm);
	printf("进程继续\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值