进程|信号

/*
当僵尸进程产生的时候,我们有两种方法可以来处理僵尸进程
1:使用kill -9 + pid 来杀死父进程
kill -9 工作原理为:向父进程发送一个进程结束信号,当父进程接收到这个信号之后,他会暂时停止正在处理的工作,转而处理信号,这个信号又恰巧是结束进程的信号,所以父进程就直接结束了
2:既然信号的工作方式是会暂停手上工作,有限处理信号的话,那么我们考虑不要向父进程发送结束进程的信号,我们可以向父进程发送一个回收子进程资源的信号,让父进程暂停忙碌状态,转而去回收子进程的资源,那么这样一来,就不会产生僵尸进程了
只有当父进程登记过相应信号后,我们才可能在程序中捕捉到该信号,然后对该信号做相应的处理
登记信号:使用函数signal
函数名:signal
头文件:signal.h
函数参数:int signum , void (*sighandler)(int)
signum : 信号类型
sighandler : 有3中情况
1:SIG_DFL 对该信号采用默认处理方式
2:SIG_IGN 对该信号采用忽略处理方式
3:sighandler 对该信号采用sighandler所编写的自定义处理方式
/
/

我们以上学到了各种情况下系统被动发送了一个信号给到一个进程,例如子进程死亡会自动发送SIGCHLD,按CTRL+C会自动发送SIGINT
那么,我们能不能主动发送一个信号
使用函数kill来主动发送一个信号
函数名:kill
头文件:sys/types.h , signal.h
参数列表:pid_t pid , int signum
分析:向进程号为 pid 的进程发送 signum 信号
返回值:成功返回0,失败返回-1,并且设置errno的值
/
/

闹钟信号:SIGALRM
SIGALRM信号,是由函数alarm发送的
函数名:alarm
头文件:unistd.h
函数参数:unsigned int second
函数分析:调用alarm后second秒,内核就会向调用该alarm函数的进程发送一个SIGALRM信号
*/

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<wait.h>
/*
② 编写一个父子孙3个进程进程链,3个进程全都死循环并且打印自身pid
要求 当键入 ctrl+c 的时候,孙子进程会让子进程变成孤儿进程,自身变成僵尸进程。
*/

void phandler(int signum){
printf(“父进程结束\n”);
exit(0);
}

void gchandler(int signum){
printf(“孙子程结束\n”);
exit(0);
}

int main(){
int res = 0;
res = fork();
if(res>0){
signal(SIGINT,phandler);
while(1){
printf(“父进程:%d\n”,getpid());
sleep(1);
}
}else if(res0){
res = fork();
if(res>0){
signal(SIGINT,SIG_IGN);
while(1){
printf(“子进程:%d\n”,getpid());
sleep(1);
}
}else if(res
0){
signal(SIGINT,gchandler);
while(1){
printf(“孙子进程:%d\n”,getpid());
sleep(1);
}
}
}
return 0;
}

/*
① 一个父进程,可以产生一个子进程
父子进程同时无线循环,并打印自己的pid。
要求:子进程能够通过ctrl+c结束运行,子进程在结束之前,主动向父进程发送一个SIGQUIT,父进程接收到SIGQUIT后,回收子进程资源,并且5秒后父进程也结束运行

② 编写一个父子孙3个进程进程链,3个进程全都死循环并且打印自身pid
	要求 当键入 ctrl+c 的时候,孙子进程会让子进程变成孤儿进程,自身变成僵尸进程。

*/

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<wait.h>

void sighandler(int signum){
if(signum == SIGINT){
kill(getppid(),SIGQUIT);
exit(0);
}else if(signum == SIGQUIT){
wait(0);
printf(“资源回收完成,程序即将退出\n”);
sleep(5);
exit(0);
}
}

int main(){
int res = fork();
if(res>0){
signal(SIGQUIT,sighandler);
signal(SIGINT,SIG_IGN);
while(1){
printf(“父进程:%d\n”,getpid());
}
}else if(res==0){
signal(SIGINT,sighandler);
while(1){
printf(“子进程:%d\n”,getpid());
}
}
return 0;
}

/*
编写一个学生链表的添加,加载和保存功能。(链表的数据域只要姓名和学号)
要求:程序进入之后,将文件中的所有学生信息加载到链表中,程序退出之前,将链表中的所有学生信息保存在文件中,这个退出包含正常退出以及ctrl+c退出
*/

#include<signal.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>

typedef struct Data{
char name[20];
int id;
}data_t;

typedef struct Student{
data_t data;
struct Student* next;
struct Student* prev;
}stu_t;

stu_t* phead;

stu_t* init_stu(){
stu_t* head = malloc(sizeof(stu_t));
memset(head,0,sizeof(stu_t));
head->next = head;
head->prev = head;
return head;
}

void print_stu(stu_t* head){
stu_t* p = head->next;
while(p!=head){
printf(“\n");
printf(“姓名 : %s\n”,p->data.name);
printf(“学号 : %d\n”,p->data.id);
p = p->next;
}
printf("
\n”);
}

void insert_stu(stu_t* head,int* id){
data_t data = {0};
printf(“请输入姓名:”);
scanf("%s",data.name);
while(getchar()!=10);
data.id = (id)++;
stu_t
newst = malloc(sizeof(stu_t));
memset(newst,0,sizeof(stu_t));
newst->data = data;
stu_t* p = head->prev;
p->next = newst;
newst->next = head;
head->prev = newst;
newst->prev = p;
}

void save_stu(stu_t* head){
stu_t* p = head->next;
int fd = open(“stuDB.txt”,O_WRONLY|O_CREAT|O_TRUNC,0664);
while(p!=head){
write(fd,&p->data,sizeof(data_t));
p = p->next;
}
close(fd);
}

void load_stu(stu_t* head,int* id){
int fd = open(“stuDB.txt”,O_RDONLY);
if(fd<0){return;}
data_t data = {0};
int res = 0;
while(1){
res = read(fd,&data,sizeof(data_t));
if(res == 0){break;}
stu_t* newst = malloc(sizeof(stu_t));
memset(newst,0,sizeof(stu_t));
newst->data = data;
stu_t* p = head->prev;
p->next = newst;
newst->next = head;
head->prev = newst;
newst->prev = p;
(*id)++;
}
close(fd);
}

void sighandler(int signum){
if(signum == SIGINT){
save_stu(phead);
exit(0);
}
}

int main(){
stu_t* head = init_stu();
phead = head;
int id = 190701;
load_stu(head,&id);
int ch = 0;
signal(SIGINT,sighandler);
while(1){
printf(“1:添加\n”);
printf(“2:打印\n”);
printf(“3:退出\n”);
scanf("%d",&ch);
while(getchar()!=10);
switch(ch){
case 1:
insert_stu(head,&id);
break;
case 2:
print_stu(head);
break;
case 3:
save_stu(head);
return 0;
}
}
return 0;
}

/*
使用信号机制,编写一个程序,该程序有一个父进程产生一个子进程。
之后父进程死循环,子进程直接结束
要求避免缠身僵尸进程
*/
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<wait.h>

void sighandler(int signum){
if(signum == SIGCHLD){
wait(0);
//exit(0);
}
}

int main(){
int res = fork();
if(res>0){
signal(SIGCHLD,sighandler);
while(1);
}else if(res==0){
printf(“子进程死亡\n”);
}
return 0;
}

demo3

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<wait.h>

int second = 1;

void sighandler(int signum){
if(signum == SIGALRM){
printf(“123\n”);
alarm(second++);
}
}

int main(){
signal(SIGALRM,sighandler);
alarm(second);
while(1);
return 0;
}

demo2-2

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>

int main(int argc,char** argv){
if(argc!=3){return 0;}
int pid = atoi(argv[1]);
int signum = 0;
if(strcmp(argv[2],“SIGKILL”)==0){
signum = SIGKILL;
}else if(strcmp(argv[2],“SIGINT”)==0){
signum = SIGINT;
}else if(strcmp(argv[2],“SIGQUIT”)==0){
signum = SIGQUIT;
}else if(strcmp(argv[2],“SIGSTOP”)==0){
signum = SIGSTOP;
}
kill(pid,signum);
return 0;
}

demo2-1

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

void sighandler(int signum){
if(signum == SIGQUIT){
printf(“捕获到 SIGQUIT 信号,程序退出\n”);
exit(0);
}else if(signum == SIGKILL){
printf(“捕获到 SIGKILL 信号,程序退出\n”);
exit(0);
}else if(signum == SIGSTOP){
printf(“捕获到 SIGSTOP 信号,程序退出\n”);
exit(0);
}
}

int main(){
signal(SIGQUIT,sighandler);
signal(SIGKILL,sighandler);
signal(SIGSTOP,sighandler);
while(1){
printf(“运行中…:%d\n”,getpid());
sleep(1);
}
return 0;
}

demo1

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>

void sighandler(int signum){
if(signum == SIGINT){
signal(SIGINT,SIG_DFL);
printf(“再按一次ctrl+c退出\n”);
//exit(0);
}
}

int main(){
signal(SIGINT,sighandler);
while(1){
printf(“1234\n”);
sleep(1);
}
return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值