`
ydbc
  • 浏览: 766640 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

Linux 信号和信号集

 
阅读更多

信号是linux所使用的进程间通信的最古老的方式。它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 。一个完整的信号周期包括三个部分,信号的产生,信号在进程中的注册,信号在进程中的注销,执行信号处理函数。如下图所示:


注意:这里信号的产生,注册,注销时信号的内部机制,而不是信号的函数实现。

对信号的响应由三种方式:

1、忽略信号,即对信号不做任何的处理。处SIGKILL和SIGSTOP除外。

2、捕捉该信号,定义信号处理函数,当信号发生时,执行信号处理函数

3、执行缺省操作,linux对每种信号都有默认的操作。

信号的发送通过kill函数和raise函数,两者的区别在于raise函数可以向本进程发送信号。




下面的代码展示了如何使用两个函数:

在实例中首先fork了一个子进程,为了保证子进程不在父进程调用kill函数之前退出,使用raise函数向子进程发送SINSTOP函数,将子进程暂停。接下来再在父进程中执行kill函数。

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

int main()
{
	pid_t pid;
	int ret;
	if((pid=fork())<0){
		perror("fork");
		exit(1);
	}
	if(pid == 0){
		raise(SIGSTOP);
		exit(0);
	}
	else{
		printf("pid=%d\n",pid);
		if((waitpid(pid,NULL,WNOHANG))==0){
			if((ret=kill(pid,SIGKILL))==0)
				printf("kill %d\n",pid);
			else{
				perror("kill");
			}
		}
	}
}
程序执行的结果:



信号处理的方法有两种,一种是使用signal函数进行处理,另一种使用信号集函数。

signal函数:

使用signal函数时只需将处理的信号和处理的函数列出即可。



下面使用代码展示如何使用signal函数:

#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
static void sig_usr(int signo);
int main(void)
{
	if(signal(SIGUSR1,sig_usr) == SIG_ERR)
		printf("Can't catch SIGUSR1");
		
		if(signal(SIGUSR2,sig_usr) == SIG_ERR)
		printf("Can't catch SIGUSR2");
		
		for(;;)
		pause();
		

}

static void sig_usr(int signo)
{
	if(signo == SIGUSR1)
		printf("recevied SIGUSR1\n");
		else if (signo == SIGUSR2)
			printf("received SIGUSR2\n");
			else
			printf("received signal %d\n",signo);
		

}

执行程序在后台运行:./signal &


第二种是信号集处理信号:

信号集是一个能表示多个信号的数据类型,sigset_t set ;set即一个信号集。
  既然是一个集合,就需要对集合进行添加/删除等操作。
  int sigemptyset(sigset_t *set); 将set集合置空
  int sigfillset(sigset_t *set); 将所有信号加入set集合
  int sigaddset(sigset_t *set,int signo); 将signo信号加入到set集合
  int sigdelset(sigset_t *set,int signo); 从set集合中移除signo信号
  int sigismember(const sigset_t *set,int signo); signo判断信号是否存在于set集合中


信号处理的过程如下:




struct sigaction {
  void (*sa_handler)();/*处理函数或SIG_IGN(忽略)或SIG_DFL(默认)*/
  sigset_t sa_mask; /*处理函数过程中被阻塞*/
  int sa_flags; /*标志位,对信号进程处理选项*/
  } ;


#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
//自定义信号处理函数
void my_func(int signum)
{
	printf("If you want to quit,please try SIGQUIT\n");
}
int main()
{
	sigset_t set,pendset;
	struct sigaction action1,action2;
	//初始化信号集为空
	if(sigemptyset(&set)<0)
		perror("sigemptyset");
		//将相应的信号加入信号集
	if(sigaddset(&set,SIGQUIT)<0)
		perror("sigaddset");
	if(sigaddset(&set,SIGINT)<0)
		perror("sigaddset");
		//设置信号集屏蔽字
	if(sigprocmask(SIG_BLOCK,&set,NULL)<0)
		perror("sigprocmask");
	else
	{
		printf("blocked\n");
		sleep(5);
	}
	if(sigprocmask(SIG_UNBLOCK,&set,NULL)<0)
		perror("sigprocmask");
	else
		printf("unblock\n");
		
		//对相应的信号进行屏蔽处理
	while(1){
		if(sigismember(&set,SIGINT)){
			sigemptyset(&action1.sa_mask);
			action1.sa_handler=my_func;
			sigaction(SIGINT,&action1,NULL);
		}else if(sigismember(&set,SIGQUIT)){
			sigemptyset(&action2.sa_mask);
			action2.sa_handler = SIG_DFL;
			sigaction(SIGTERM,&action2,NULL);
		}
	}
}
打开两个终端,在一个终端中执行该程序,在另一个终端中发送信号。

发送信号:kill -SIGINT 进程号

kill -SIGQUIT 进程号

程序运行的结果:




分享到:
评论

相关推荐

    第9章linux信号与定时器

    ### 第9章Linux信号与定时器 #### 一、进程间通信与信号 ...总之,Linux信号和定时器是实现进程间通信和时间管理的关键组件。通过深入理解它们的工作原理和使用方法,开发者可以构建出更加健壮和高效的Linux应用程序。

    linux 信号量中断 时间

    ### Linux信号量、中断与时间管理详解 #### 一、信号量的概念与分类 在Linux系统中,**信号量(Signal)** 是一种重要的进程间通信(IPC)手段,主要用于一个进程向另一个进程发送简短的消息。尽管信号量本身无法携带...

    linux 信号使用全集

    ### Linux信号量使用全集解析 #### 一、信号量概览 信号量是一种关键的同步机制,在Linux系统中主要用于管理共享资源的访问,确保在任何时间点只有一个进程(或线程)能够独占资源。当信号量的值为正时,表明资源...

    Linux信号的阻塞和投递研究

    2. **`sigemptyset()`** 和 **`sigfillset()`**:前者初始化信号集为空集,后者初始化信号集包含所有信号。 3. **`sigaddset()`** 和 **`sigdelset()`**:用于向信号集中添加或删除信号。 4. **`sigprocmask()`**:...

    linux 多进程同步-信号量集

    linux多任务(进程)同步-信号量集

    Linux下C语言编程--信号处理函数.

    - **`sigfillset`**:初始化信号集为包含所有信号。 - **`sigaddset`**:向信号集中添加信号。 - **`sigdelset`**:从信号集中删除信号。 - **`sigismember`**:检查信号是否存在于信号集中。 - **`sigprocmask`**:...

    linux下多任务的信号量集实现

    linux下多任务的信号量集实现,花了哥两周的时间。

    01--Linux系统编程-信号.docx

    Linux内核通过进程控制块(PCB,即task_struct结构体)来存储关于信号的信息,包括阻塞信号集和未决信号集。阻塞信号集允许进程临时屏蔽某些信号,使其不会立即处理,而是等到解除屏蔽后处理。未决信号集则记录了...

    linux c 进程间通信 信号灯 程序源码

    本文将详细讲解Linux C编程中的一种进程间通信方式——信号灯(Semaphore),并结合提供的程序源码进行解析。 信号灯是同步原语之一,它允许进程在执行过程中对某些资源进行互斥访问或同步操作。信号灯由两个基本...

    14_linux信号量专题讲座-王保明.rar

    这个讲座深入浅出地讲解了Linux信号量的理论和实践,有助于提升开发者在多进程和多线程环境下的编程能力,更好地理解和解决并发问题。通过学习,我们可以更熟练地利用信号量来保护共享资源,实现高效的并发控制,...

    Linux信号量1

    【Linux信号量1】 在多进程环境中,当多个进程需要访问同一共享资源时,可能会出现竞态条件,导致数据不一致。为了解决这个问题,Linux提供了信号量机制,这是一种同步工具,用于协调进程间的访问控制。 信号量是...

    linux信号量专题编程笔记.docx

    综上所述,Linux信号量是解决并发控制问题的重要手段,通过合理的使用信号量,可以有效地避免竞争条件,实现进程间的同步和互斥,从而保证系统的稳定和高效运行。在实际编程中,理解并熟练运用信号量API,可以构建出...

    Linux多进程通信-信号量,共享内存示例

    在Linux中,信号量分为两种类型:互斥量(mutex)和信号量集。互斥量是二进制信号量,用于保护临界区,确保同一时间只有一个进程可以访问共享资源。信号量集则可以表示更复杂的计数,允许多个进程同时访问但控制访问...

    Linux环境进程间通信 信号灯

    #### 二、Linux信号灯 在Linux环境下,系统支持的信号灯主要是系统V信号灯。系统V信号灯提供了更为灵活的信号灯操作和管理机制。以下将详细介绍Linux下的系统V信号灯及其相关API。 **系统V信号灯特点:** - **持久...

    liunx信号概念及c信号函数的使用

    在Linux操作系统中,信号(Signal)是一种...通过对Linux信号和C语言信号函数的深入理解和实践,可以编写出能够有效响应系统事件和异常的健壮程序。在实际开发中,合理利用信号机制能够增强程序的容错性和可维护性。

    Linux进程间通信-信号量通信进程互斥实例.pdf

    在Linux中,信号量可以分为两种类型:整型信号量(互斥锁)和记录型信号量(可以有多个等待进程)。在本实例中,使用的是整型信号量,它用于实现进程互斥。 【进程互斥】进程互斥是指在同一时间只有一个进程可以...

    最全面的Linux信号量学习.pdf

    Linux信号量是一种用于进程和线程同步的重要机制,主要用来保护共享资源,确保在任何时刻只有一个进程或线程可以访问特定的资源。信号量的值代表资源的状态,正数表示资源可用,0表示资源被占用,等待其他线程释放。...

    LinuxC_函数全集

    Linux C 函数全集是开发者们不可或缺的参考资料,它涵盖了C语言在Linux环境下的众多核心函数,帮助程序员理解和使用这些功能强大的工具。 Linux C 函数全集中,我们可以找到以下主要的知识点: 1. **标准输入/输出...

    使用共享内存及信号量实现进程间通信例子

    `semget`用于创建信号量集,`semop`执行信号量操作(如P(等待)和V(释放)操作),`semctl`用于管理信号量集,如初始化或删除。 在实际应用中,信号量常与共享内存结合使用,确保对共享内存的访问是同步的。例如...

    Linux下C语言编程——信号处理

    - `sigfillset`:初始化信号集包含所有信号。 - `sigaddset`:向信号集中添加信号。 - `sigdelset`:从信号集中移除信号。 - `sigismember`:检查信号是否存在于信号集中。 - `sigprocmask`:设置进程的信号屏蔽集。...

Global site tag (gtag.js) - Google Analytics