学习APUE笔记5-并发

并发(信号 线程)

 

同步

异步

异步事件的处理:查询法,通知法

一、信号

1、信号的概念

信号是软件中断

 

2、signal();

 

ANSI C 信号处理:

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

当signum信号到来执行handler。

返回值:成功,返回以前的信号处理配置;出错,返回SIG_ERR。

注意:没有被忽略的信号(某些信号的默认行为就是忽略)会唤醒正在睡眠的进程;

如果信号被捕捉则唤醒后先执行信号处理函数,然后继续执行,否则进程直接结束.

 

信号会打断阻塞的系统调用。

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

 

void int_handler(int s)

{

write(1,"!",1);

}

 

int main()

{

int i;

// signal(SIGINT,SIG_IGN);//SIGINT中断一个信号,SIG_IGN忽略一个信号。

signal(SIGINT,int_handler);

 

for(i = 0 ; i < 10; i++)

{

write(1,"*",1);

sleep(1);

}

 

exit(0);

}

 

3、信号的不可靠

标准信号会丢失,实时信号不会丢失。

信号的行为不可靠。

信号到来时内核为其布置现场,信号在处理这个行为的同时,又来了一个新的相同的信号,

内核有可能会将执行现场布置在同一个位置,旧的执行现场将会被新的信号的执行现场所覆盖。

方法:构造一个链实结构。

 

4、可重入函数

第一次调用还没结束第二次调用又来了,但不会出错。

所有的系统调用都是可重入的,一部分库函数也是可重入的,比如:memcpy。

不可重入:rand产生随机值,但是rand_r就是可重入的。

 

5、信号的响应过程

内核至少为每个进程维护来两个位图mask&pending

信号从收到到响应有一个不可避免的延迟

思考:

1>如何忽略掉一个信号的?

将mask位一直置0

2>标准信号为什么要丢失。

mask置零时来多个信号但却不会执行,所以会丢失。

3>标准信号的响应没有严格的顺序。

4>不能从信号处理函数中随意的往外跳。(sigsetjmp, siglongjmp)

6、常用函数

 

1>向进程发送信号:int kill(pid_t pid, int sig);

返回值:成功返回0,失败返回-1并设置errno。

pid > 0 发送给进程 ID 是 pid 的进程

pid = 0 发送给与调用进程的同组进程

pid = -1 发送给有权限发送所有进程

pid < -1 发送给进程组|pid|的进程

注意:超级用户进程拥有向任何进程发送信号的权限,普通进程只能发送给与发送者 UID或者 EUID 相同的进程。

 

2>向自己发送信号,准确的说是发送给调用线程:int raise(int sig);

返回值:成功0,失败非0.

注意:这个函数发送的信号如果被捕捉,则先执行完信号处理函数 raise 才返回

 

2.1>获取或设置一个间隔计时器的值:

int getitimer(int which, struct itimerval *curr_value);

int setitimer(int which, const struct itimerval *new_value,

              struct itimerval *old_value);

which代表设置那个时钟 ITIMER_REAL、ITIMER_VIRTUAL、ITIMER_PROF

第二个参数代表新的时钟周期。

struct itimerval {

       struct timeval it_interval; /* Interval for periodic timer */

       struct timeval it_value;    /* Time until next expiration */

      };

struct timeval {

       time_t      tv_sec;         /* seconds */

       suseconds_t tv_usec;        /* microseconds */

      };

返回值:成功0,出错-1,并设置errno。

例:使用单一计时器,利用alarm或setitimer构造一组函数,实现任意数量的计时器。

//漏桶 srtitimer替换alarm

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <errno.h>

#include <signal.h>

#include <unistd.h>

#include <sys/time.h>

 

#define CPS 10

#define BUFSIZE CPS

 

static volatile int loop = 1;

 

void alrm_handler(int s)

{

// alarm(1);

loop = 0;

}

 

int main(int argc,char **argv)

{

int sfd,dfd = 1;

char buf[BUFSIZE];

int len,ret,pos;

struct itimerval itv;

 

if(argc < 2)

{

fprintf(stderr,"Usage:%s <srcfile>\n",argv[0]);

exit(1);

}

 

signal(SIGALRM,alrm_handler);

// alarm(1);

 

itv.it_interval.tv_sec = 1;

itv.it_interval.tv_usec = 0;

itv.it_value.tv_sec = 1;

itv.it_value.tv_usec = 0;

if(setitimer(ITIMER_REAL,&itv,NULL) < 0)

{

perror("setitimer()");

exit(1);

}

do

{

sfd = open(argv[1],O_RDONLY);

if(sfd < 0)

{

if(errno != EINTR)

{

perror("open()");

exit(1);

}

}

}while(sfd < 0);

 

while(1)

{

while(loop)

pause();//避免盲等

loop = 1;

 

while((len = read(sfd,buf,BUFSIZE)) < 0)

{

if(errno == EINTR)

continue;

perror("read()");

break;

}

if(len == 0)

break;

 

// len > 0

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值