IPC进程间通信

发布于:2024-08-18 ⋅ 阅读:(100) ⋅ 点赞:(0)

信号

信号是一种终端机制,程序运行到一半的时候接收到了某种通知,程序就会立刻中断运行,转而去处理通知。

登记信号

一个进程只会接收默认的几个信号

如果想要让一个进程接收特定信号的话,必须提前在该进程中登记一下想要接收的信号

typedef void (*sighandler_t)(int);

原型:sighandler_t signal(int signum, sighandler_t handler); .
调用:signal(1/2/3/.....,handler)
功能描述:
    将signum信号,登记为当前进程所能捕获的信号。当进程捕获到 signum 信号之后,就会中断当前的运行,转而运行 handler函数
参数 signum:想要登记的信号的编号,使用 kill -l 查看
参数 handler:void(int)类型的函数指针,信号处理函数
    handler除了传入一个函数指针之外,还有2个选项
        SIG_IGN:该信号捕获到之后,忽略处理
        SIG_DFL:该信号被捕获到之后,执行默认的操作

原型 void handler(int signum)
调用:signal(1/2/3/.....,handler)
功能描述:一旦进程捕获到一个被signal登记的信号之后,就会调用handler函数
参数 signum:当前被捕获到的

几个常用信号
    SIGINT:当键盘键入 ctrl + c 时候发出
    SIGTSTP:当键盘键入 ctrl + z 时候发出
    SIGCHLD:当子进程死亡的时候,自动的向其父进程发出的信号
    
只能默认处理的信号:SIGKILL 和 SIGSTOP 无法自定义处理 或者 忽略处理
不能被忽略的信号:SIGSEGV段错误信号,但是段错误信号可以自定义处理

练习

父子进程同时捕获登记SIGINT信号

父进程:输出我是父进程

子进程:输出我是子进程

#include <stdio.h>
#include <string.h>
#include <stdlib.h>	
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

pid_t pid;

void handler(int signum)
{
		printf("%d\n",getpid());
	if(signum == SIGINT)
	{
		if(pid>0)
		{
		printf("我是父进程\n");
		exit(0);
		}
		else if(0==pid)
		{
		printf("我是子进程\n");
		exit(0);
		}
	}
}

int main(int argc, const char *argv[])
{
	pid_t pid=fork();
	if(pid>0)
	{
		signal(SIGINT,handler);
		printf("%d\n",getpid());
	}
	else
	{
		signal(SIGINT,handler);
		printf("%d\n",getpid());
	}
	while(1);
	return 0;
}

当一个子进程死亡的时候,会自动的向其父进程发出SIGCHLD信号 要求实现:当父进程接收

到子进程死亡信息的时候,回收子进程的资源,防止僵尸进程的出现

当一个子进程死亡的时候,会自动的向其父进程发出SIGCHLD信号 要求实现:当父进程接收

到子进程死亡信息的时候,回收子进程的资源,防止僵尸进程的出现

追加要求:父进程使用

循环创建500个子进程,每一个子进程创建完毕后,立刻死亡

要求测试,是否产生僵尸进程,

并做到没有僵尸进程

标准的不会产生僵尸进程的模型

#include <stdio.h>
#include <string.h>
#include <stdlib.h>	
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

int i=0;

void handler(int signum)
{
	while(1)
	{	
		pid_t w=waitpid(-1,0,WNOHANG);
		if(-1==w)
			return;
	}
	printf("子进程的资源已被回收\n");
}

int main(int argc, const char *argv[])
{
	for(int i=0;i<500;i++)
	{
		pid_t pid=fork();
		if(pid>0)
		{
			printf("ppid=%d\n",getpid());
			signal(SIGCHLD,handler);
			//wait(0);
		}
		else
		{
			int p=getpid();
			printf("pid=%d\n",p);
			kill(getpid(),SIGKILL);
			break;
		}
	}
	while(1);
	return 0;
}

4:有2个.c文件,每个.c文件都拥有一对父子进程,总共4个进程 A a B b 现在要求实现一个多

米诺骨牌的效果:

按ctrl+c结束a进程的运行,a进程结束运行之前,通过kill函数向b进程发送SIGINT信号,b进

程死亡后,B进程回收b进程的资源后,B进程再使用kill函数向A进程发送SIGTSTP信号后,大B进程结束运行。A进程接受到B进程的SIGTSTP信号后,会后a进程的资源后也结束运行

注意:kill函数要求获得另一个进程的pid,使用文件IO

这个题需要预习一个函数叫做 kill 函数

A.c文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>	
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

void handle(int signum)
{
	if(signum==SIGINT)
	{
		FILE* p=fopen("./b的pid","r");
		pid_t b_pid;
		fread(&b_pid,4,1,p);
		kill(b_pid,SIGINT);
		fclose(p);
		printf("a死亡\n");
		exit(0);
	}
	if(signum==SIGTSTP)
	{
		wait(0);
		printf("A结束\n");
		exit(0);
	}
}

int main(int argc, const char *argv[])
{
	pid_t pid=fork();
	if(pid>0)
	{	
		signal(SIGINT,SIG_IGN);
		FILE* p1=fopen("./A的pid","w");
		pid_t A_pid=getpid();
		fwrite(&A_pid,4,1,p1);

		fclose(p1);

		signal(SIGTSTP,handle);
	}
	else
	{
		signal(SIGINT,handle);
	}
	while(1);
	return 0;
}

B.c文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>	
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

void handle(int signum)
{
	if(signum==SIGINT)
	{
		sleep(1);
		printf("b死亡\n");
		exit(0);
	}
	if(signum==SIGCHLD)
	{
		sleep(1);
		while(waitpid(-1,0,WNOHANG)!=-1);	
		FILE* p1=fopen("./A的pid","r");
		pid_t A_pid;
		fread(&A_pid,4,1,p1);
		kill(A_pid,SIGTSTP);
		fclose(p1);
		printf("B死亡\n");
		exit(0);

	}
}

int main(int argc, const char *argv[])
{
	pid_t pid=fork();
	if(pid>0)
	{
		signal(SIGCHLD,handle);
	}
	else
	{
		FILE* p=fopen("./b的pid","w");
		pid_t b_pid=getpid();
		fwrite(&b_pid,4,1,p);

		fclose(p);
		signal(SIGINT,handle);
	}
	while(1);
	return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到