如何使用信号机制 (SIGUSR1) 来在父子进程之间传递信息

/*  子进程捕捉SIGUSR1,父进程发送SIGUSR1给子进程,
子进程收到SIGUSR1时,就会该信号的信号值打印出来 */

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

void signal_fun(int sig)  //sig就是收到的信号值
{
	printf("catch sig = %d\n",sig);
}

int main()
{
	pid_t x;
	
	x = fork();
	
	//父进程发送信号
	if(x > 0)
	{
		printf("before sleep!\n");
		sleep(1);  //确保子进程signal()先运行
		printf("after sleep!\n");
		kill(x,SIGUSR1);
		
		wait(NULL);
	}
	
	//子进程捕捉信号
	if(x == 0)
	{
		//提前捕捉SIGUSR1这个信号,将来子进程收到这个信号,则
		//运行signal_fun这个函数
		printf("before signal!\n");
		signal(SIGUSR1,signal_fun);
		printf("after signal!\n");
		
		//静静地等待信号的到来
		pause();
	}
	
}

执行过程

  1. 父进程首先创建一个子进程。
  2. 子进程设置好信号处理函数,准备好接收 SIGUSR1 信号。
  3. 父进程睡眠 1 秒钟,确保子进程完成信号处理函数的注册。
  4. 父进程向子进程发送 SIGUSR1 信号,子进程捕获信号并执行 signal_fun 函数,打印信号值。
  5. 父进程等待子进程退出
  • signal():该函数用于设置信号的处理函数,在此代码中,子进程用它来捕捉 SIGUSR1 信号,并指定处理函数 signal_fun
  • kill():父进程用 kill() 发送信号给子进程,实际上 kill() 是用来发送信号的kill(x, SIGUSR1) 发送 SIGUSR1 信号给进程 x(子进程的 PID)。
  • pause():子进程在这里阻塞,直到接收到信号才会继续执行。

以下是 signal(), kill(), 和 pause() 这三个函数的详细解释以及使用方法:

1. signal() 函数

功能:

signal() 函数用于设置信号的处理程序。通过这个函数,程序可以指定当接收到特定信号时,程序应该执行哪个处理函数。

函数原型:
void (*signal(int signum, void (*handler)(int)))(int);
  • signum:信号的编号,表示你要捕获的信号(例如,SIGUSR1)。
  • handler:信号处理程序的指针,即当进程收到信号时,要执行的函数。如果该参数为 SIG_DFL,表示使用默认的信号处理方式;如果为 SIG_IGN,表示忽略该信号。
示例:
void signal_fun(int sig)  // 信号处理函数
{
    printf("Received signal: %d\n", sig);
}

int main()
{
    // 捕捉 SIGUSR1 信号并设置信号处理函数
    signal(SIGUSR1, signal_fun);  
    
    // 进程进入休眠,等待信号
    pause();
    return 0;
}
  • 在这个例子中,当程序收到 SIGUSR1 信号时,signal_fun 函数将被调用,打印信号值。
  • signal() 设置了当接收到 SIGUSR1 时,调用 signal_fun 函数。

2. kill() 函数

功能:

kill() 函数用于向指定进程发送信号。它通常用于进程间的信号传递。

函数原型:
int kill(pid_t pid, int sig);
  • pid:目标进程的 PID。该值可以是:

    • 正数:表示要发送信号给指定 PID 的进程。
    • 0:表示向当前进程组中的所有进程发送信号。
    • -1:表示向所有进程发送信号(除了系统进程和本进程)。
    • 负数:表示向指定进程组的所有进程发送信号。
  • sig:要发送的信号编号(如 SIGUSR1)。

示例:
pid_t pid = fork();
if (pid > 0)
{
    // 父进程
    kill(pid, SIGUSR1);  // 向子进程发送 SIGUSR1 信号
}
else if (pid == 0)
{
    // 子进程
    signal(SIGUSR1, signal_fun);  // 捕获 SIGUSR1 信号并处理
    pause();  // 阻塞,等待信号
}
  • 在父进程中,使用 kill(pid, SIGUSR1) 向子进程发送 SIGUSR1 信号。
  • 在子进程中,使用 signal(SIGUSR1, signal_fun) 捕获 SIGUSR1 信号并执行 signal_fun 函数。

3. pause() 函数

功能:

pause() 函数会让进程进入休眠,直到接收到信号才会继续执行。它通常与信号处理结合使用。

函数原型:
int pause(void);
  • 返回值pause() 没有返回值,它会一直阻塞直到收到信号。
示例:
void signal_fun(int sig)
{
    printf("Received signal: %d\n", sig);
}

int main()
{
    signal(SIGUSR1, signal_fun);  // 捕获 SIGUSR1 信号
    pause();  // 阻塞,等待信号
    return 0;
}
  • 在这个例子中,pause() 会阻塞子进程,直到收到信号(比如 SIGUSR1)。当收到信号时,会调用 signal_fun 函数并打印信号值。

总结:

  1. signal() 用于设置信号的处理函数,当进程接收到特定信号时,调用对应的处理函数。
  2. kill() 用于发送信号给指定进程,可以通过该函数向子进程、父进程或其他进程发送信号。
  3. pause() 用于让进程阻塞,直到接收到信号才继续执行,常与信号处理函数配合使用。

这三个函数在进程间通信和信号处理方面非常有用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值