linux 进程间广播,Linux系统编程之进程间通信之浅谈信号

我们接着谈Linux学习过程中一个重要的话题--信号。

一、信号的概念:

信号是一种软件中断,它提供了一种处理异步事件的方法,也是进程间唯一的异步通信方式。

二、信号的来源:

1、硬件方式:

当用户按下终端上某些键时,将产生信号。

硬件异常产生信号:除0操作、访问非法空间……

2、软件方式

用户在终端下调用kill命令向进程发送任意信号

进程调用kill或者sigqueue函数发送信号。

当检测到某种软件条件发生时,如alarm或者setimer

三、信号处理

1、信号的捕捉和处理

1、signal函数

a、函数作用:

signal函数用来设置进程在接收到信号时的动作。

b、函数原型:#include 

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

c、参数解析与函数说明:

signal函数会根据参数signal指定的信号编号来设置该信号的处理函数。当指定的信号到达时就会

跳到参数hander指定的函数执行。如果hander不是函数指针,则必须时常数SIG_IGN忽略该信号)或者S

IG_DFL(对该信号执行默认操作)。hander是 一个函数指针,它所指向的函数的类型时sighandel_t,即

它 所指向的函数有一个int型参数,且返回值的类型为void。

d、样这里给出signal处理信号的例子:/**********************************************************

*    > File Name: signal-1.c

*    > Author:xiao_k

*    > Mail:18629086235@163.com

*    > Created Time: Fri 23 Feb 2018 12:05:46 AM CST

**********************************************************/

#include

#include

#include

#include

#include

#include

//信号处理函数

void do_sig(int num)

{

printf("I am do_sig\n");

}

int main()

{

//安装处理信号

signal(SIGINT,do_sig);

while(1)

{

printf("********\n");

sleep(1);

}

return 0;

}

2、sigaction函数

a、函数作用:

sigction函数可以用来检查和设置进程在接收信号时的动作。

b、函数原型

#include

int sigaction(int signum, const struct sigaction *act,

struct sigaction *oldact);

c、参数解析与函数说明:

sigzction函数会根据参数signum指定的信号编号来设置该信号的处理函数。参数signum可以是除了

SIGKILLh和SIGSTOP以外的任何信号。

如果参数act 不是空指针,则为signum设置新的信号处理函数;

如果oldzct不是空指针,则旧的信号处理函数将被存储在oldact中,struct sigaction的定义如下:

struct sigaction {

void     (*sa_handler)(int);

void     (*sa_sigaction)(int, siginfo_t *, void *);

sigset_t   sa_mask;

int        sa_flags;

void     (*sa_restorer)(void);

};

sa_handler可以是常数SIG_DFL或者SIG_IGN,或者是一个信号处理函数名。

sa_sigaction也是用来指定信号的signum的处理函数。

sa_mask成员声明了一个信号集,在调用信号捕捉函数之前,该信号会增加到进程的信号屏蔽码中,

新的信号屏蔽码会自动包括正在处理的信号(sa_flags未指定SA_NODEFER或者SA_NOMASK)。当从信号捕

捉函数返回时,进程的信号屏蔽码会恢复为原来的值。因此,当处理一个给定的  信号时,如果这种

信号再次发生,那么它会阻塞直到本次信号处理结束为止。若这种信号发生了多次,则对于不可靠信号,

即本次信号处理结束以后只会再次处理一次(相当于丢失了信号),对于可靠信号(实时信号),则会

被阻塞多次,即信号不会丢失,信号发生了多少次就会调用信号处理函数多少次。

sa_flags成员用来说明信号处理的其他相关操作。

当使用三参数的sa_sigaction来指定信号处理函数时,它的第 二个参数可以用来传递数据,其定义

如下:

siginfo_t {

int      si_signo;    /* Signal number */

int      si_errno;    /* An errno value */

int      si_code;     /* Signal code */

int      si_trapno;   /* Trap number that caused

hardware-generated signal (unused on most architectures) */

pid_t    si_pid;      /* Sending process ID */

uid_t    si_uid;      /* Real user ID of sending process */

int      si_status;   /* Exit value or signal */

clock_t  si_utime;    /* User time consumed */

clock_t  si_stime;    /* System time consumed */

sigval_t si_value;    /* Signal value */

int      si_int;      /* POSIX.1b signal */

void    *si_ptr;      /* POSIX.1b signal */

int      si_overrun;  /* Timer overrun count;POSIX.1b timers */

int      si_timerid;  /* Timer ID; POSIX.1b timers */

void    *si_addr;     /* Memory location which caused fault */

int      si_band;     /* Band event */

int      si_fd;       /* File descriptor */

}

d、同样给出 sigaction的测试用例/**********************************************************

*    > File Name: sigaction-1.c

*    > Author:xiao_k

*    > Mail:18629086235@163.com

*    > Created Time: Fri 23 Feb 2018 01:47:43 AM CST

**********************************************************/

#include

#include

#include

#include

#include

int temp = 0;

//信号处理函数

void do_sigact(int num)

{

printf("recv SIGINT\n");

sleep(5);

temp +=1;

printf("the value of temp is :%d\n",temp);

printf("in do_sigact,after sleep\n");

}

int main()

{

struct sigaction act;

//结构体赋值

act.sa_handler = do_sigact;

act.sa_flags = SA_NOMASK;

//安装信号处理函数

sigaction(SIGINT,&act,NULL);

while(1)

{

printf("********************\n");

sleep(1);

}

return 0;

}

编写信号处理函数时,要注意不要使用不可重入的函数,使用了不重入的函数将将产生不可预料的结果。

上边就是sigaction函数的基本用法,复杂的用法后边使用。

补充:满足下列条件的函数是不可重入的:

a、使用了静态的数据结构,如getgrpid(),全局变量等。

b、函数实现时,调用了malloc()或者free()函数。

c、函数实现时,使用了标准I/O函数。

3、pause()函数

a、函数作用:

pause函数使调用进程挂起直到捕捉到一个信号。pause函数会令目前的进程暂停(进入睡眠状态),

直到被信号(signal)所中断,该函数只返回-1,并将errno设置为EINTR。

b、函数原型:

#include

int pause(void);

四、信号的发送:

信号的发送主要由函数kill、raise、sigqueue、alarm、setitimer以及 abort来完成。

1、kill函数

a、函数作用:

kill函数用来发送信号给指定的进程。

b、函数原型#include 

#include 

int kill(pid_t pid, int sig);

c、参数解析与函数说明:

该函数的行为与第二个参数pid的取值有关,第二个参数sig表示信号编号:

如果pid时正数,则发送信号sig给进程号为pid的进程;

果pid为0,则发送信号sig给当前进程所属进程组里的所有进程;

如果pid为-1,则把信号sig广播给系统内的除1号进程和自身以外的所有进程;

如果pid为比-1还小的负数,则发送信号sig给属于进程组-pid的所有进程;

如果参数sig是0,则kill(),仍然执行正常的错误检查,但不发送信号。可以利用这一点来确定某

进程是否有权向另外一个进程发送信号。如果向一个并不存在的进程发送空信号,则kill()返回-1,

errno则被设置为ESRCH。

注意:只有具有root权限的进程才能向其他任意一个进程发送信号,非root权限的进程只能向属于同一

个组成或者同一个用户创建的进程发送信号。

2、raise函数

a、函数作用:

raise函数是ANSI C 而非POSIX标准定义的。用来给调用它的进程发送信号。

b、函数原型#include 

int raise(int sig);

3、sigqueue函数

a、函数作用

sigqueue函数是一个比较新的发送信号的函数,它支持信号带有参数,从而可以与函数sigaction配

合使用。

b、函数原型

#include

int sigqueue(pid_t pid, int sig, const union sigval value);

c、参数解析与函数说明:

sigqueue用来发送给信号sig给进程pid。与kill系统调用不同的是,sigqueue在发送信号的同时

还支持信号携带参数;另外一个不同点是sigqueue 不能给一组进程发送信号,参数value是一个共用

体,其定义如下:

union sigval {

int   sival_int;

void *sival_ptr;

};

4、alarm函数

a、函数作用

alarm函数可以用来设置定时器,定时器超时将产生SIGALRM信号给调用进程。

b、函数原型#include 

unsigned int alarm(unsigned int seconds);

c、参数解析与函数说明:

参数seconds表示设定的秒数,经过seconds后,内核将给调用该函数的进程发送SIGALRM信号。如果seconds为0,

则不再发送SIGALRM信号,最新一次调用alarm函数将取消之前一次的设定。

5、abrot函数

a、函数作用:

abrot函数用来向进程发送SIGABRT信号。

b、函数原型#include 

void abort(void)

上边我只对信号的基本用法做了总结,后边将对信号的高级用法做单独总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程间通信是指在不同进程进行数据交换和同步的一种技术。Linux提供了多种进程间通信的方式,包括管道、消息队列、共享内存和信号量等。在实验六中,我们将学习如何使用这些方式进行进程间通信。 1. 管道 管道是一种半双工的通信方式,它可以在两个进程传递数据。在Linux中,管道分为匿名管道和命名管道。匿名管道只能用于父子进程的通信,而命名管道可以用于任意两个进程的通信。 使用匿名管道进行进程间通信的步骤如下: - 父进程创建管道,并调用fork函数创建子进程。 - 子进程通过管道接收数据。 - 父进程通过管道发送数据。 - 子进程接收到数据后进行处理。 使用命名管道进行进程间通信的步骤如下: - 创建命名管道。 - 打开命名管道并进行读写操作。 2. 消息队列 消息队列是一种进程间通信机制,它允许不同进程通过一个消息传递序列来进行通信。在Linux中,每个消息都有一个类型,接收进程可以选择接收某个特定类型的消息。 使用消息队列进行进程间通信的步骤如下: - 创建消息队列。 - 发送消息到消息队列。 - 接收消息并进行处理。 3. 共享内存 共享内存是一种进程间通信的方式,它允许不同进程共享同一个物理内存区域。这种方式比较高效,但需要考虑进程的同步和互斥问题,否则会出现数据不一致的情况。 使用共享内存进行进程间通信的步骤如下: - 创建共享内存区域。 - 进程通过共享内存区域进行数据交换。 - 进程需要进行同步和互斥操作。 4. 信号信号量是一种进程同步的机制,它可以用来保证不同进程的共享资源在同一时刻只能被一个进程访问。在Linux中,每个信号量都有一个计数器,当计数器为0时,进程需要等待;当计数器大于0时,进程可以继续执行。 使用信号量进行进程间通信的步骤如下: - 创建信号量。 - 进程信号量进行P操作(等待)。 - 进程信号量进行V操作(释放)。 总体来说,不同的进程间通信方式各有优缺点,应根据实际需求选择适合的方式。在实验六中,我们将通过编写代码来学习如何使用这些方式进行进程间通信

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值