分享
分销 收藏 举报 申诉 / 7
播放页_导航下方通栏广告

类型linux信号与系统调用的关系.doc

  • 上传人:xrp****65
  • 文档编号:8750317
  • 上传时间:2025-02-28
  • 格式:DOC
  • 页数:7
  • 大小:47.50KB
  • 下载积分:10 金币
  • 播放页_非在线预览资源立即下载上方广告
    配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    linux 信号 系统 调用 关系
    资源描述:
    信号与系统调用的关系: 当一个进程正在执行一个系统调用时,如果向该进程发送一个信号,那么对于大多数 系统调用来说,这个信号在系统调用完成之前将不起作用,因为这些系统调用不能被信号 打断。但是有少数几个系统调用能被信号打断,例如: wait(),pause()以及对慢速设备 (终端、 打印机等)的 read()、 write()、 open()等。如果一个系统调用被打断,它就返回-1,并将 errno 设为 EINTR。可以用下列代码来处理这种情况: if (wirte(tfd,buf,SIZE)<0) { if (errno==EINTR) { warn(“ Write interrupted.” ); … … } } 信号的复位: 在 Linux 中,当一个信号的信号处理函数执行时,如果进程又接收到了该信号,该信 号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用 相应的处理函数。下面的程序演示了这一点: #include <stdio.h> #include <signal.h> int catch(int sig); //信号绑定函数,必须在main函数前声明。 int main(void) { printf("the program is starting.\n"); signal(SIGINT, catch);//接受到SIGINT信号,执行绑定的catch函数 //signal(SIGINT, SIG_DFL);//SIG_DFL 恢复成系统的缺省动作 //signal(SIGINT, SIG_IGN);//告诉进程将 SIGINT 信号忽略,CTRL+C sleep(10); printf("the end.\n"); return 0; } int catch(int sig) { printf("Interrupt called.\n"); sleep(4); printf(“Interrupt Func end.\n”); } 执行它,结果如下: the program is starting. <ctrl+c> Interrupt called <ctrl+c> Interrupt Func end. Interrupt called Interrupt Func end. the end 只能保存一个CTRL+C。 如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中 断:the program is starting. <ctrl+c> Interrupt called <ctrl+\> Quit called Quit ended. Interrupt Func end。 the ended. 在进程间发送信号: 个进程通过对 signal()的调用来处理其它进程发送来的信号。一个进程也可以向其它的进程发送信号。这一操作是由系统调用 kill()来完成的。 kill()在 linux 系统库 signal.h中的函数声明:int kill(pid_t pid, int sig); 参数 pid 指定了信号发送的对象进程:它可以是某个进程的进程标识符(pid),也可以是以下的值: 如果 pid 为零,则信号被发送到当前进程所在的进程组的所有进程; 如果 pid 为-1 ,则信号按进程标识符从高到低的顺序发送给全部的进程(这个过程受 到当前进程本身权限的限制); 如果 pid 小于-1,则信号被发送给标识符为 pid 绝对值的进程组里的所有进程。 需要说明的是,一个进程并不是向任何进程均能发送信号的,这里有一个限制,就是 普通用户的进程只能向具有与其相同的用户标识符的进程发送信号。也就是说,一个用户 的进程不能向另一个用户的进程发送信号。只有 root 用户的进程能够给任何线程发送信号。 参数 sig 指定发送的信号类型。它可以是任何有效的信号。 由于调用 kill()的进程需要直到信号发往的进程的标识符,所以这种信号的发送通常只 在关系密切的进程之间进行,比如父子进程之间。 下面是一个使用 kill()调用发送信号的例子。这个程序建立两个进程,并通过向对方发 送信号 SIGUSR1 来实现它们之间的同步。这两个进程都处于一个死循环中,在接收对方发 送的信号之前,都处于暂停等待中。这是通过系统调用 pause()来实现的,它能够使一个程 序暂停,直至一个信号到达,然后进程输出信息,并用 kill 发送一个信号给对方。当用户 按了中断键,这两个进程都将终止。 #include <signal.h> int ntimes=0; main() { int pid,ppid; int p_action(), c_action(); /* 设定父进程的 SIGUSR1 */ signal(SIGUSR1,p_action); switch(pid=fork()) { case -1: /*fork 失败*/ perror("synchro"); exit(1); case 0: /*子进程模块*/ /* 设定子进程的 SIGUSR1 */ signal(SIGUSR1,c_action); /* 获得父进程的标识符*/ ppid=getppid(); for(;;) { sleep(1); kill(ppid,SIGUSR1); pause(); } - 58- Linux 网络编程 /*死循环*/ break; default: /*父进程模块*/ for (;;) { pause(); sleep(1); kill(pid,SIGUSR1); } /*死循环*/ } } p_action() { printf("Patent caught signal #%d\n",++ntimes); } c_action() { printf("Child caught signal #%d\n",++ntimes); } 程序运行结果如下: Patent caught signal #1 Child caught signal #1 Patent caught signal #2 Child caught signal #2 Patent caught signal #3 Child caught signal #3 Patent caught signal #4 Child caught signal #4 <ctrl+c> kill 命令用于向一个运行进程发送信号,它发送的信号默认为 SIGTERM,但是也可以指定为其它信号。我们可以直接用信号的号码来指定 kill 命令所发送信号之类型,也可以用符号名指定。比如可以用下面的命令来完成向进程标识符为 1234 的进程发送 SIGINT 信号: kill – s SIGINT 1234 系统调用 alarm() 和 pause(): alarm()它可以建立一个进程的报警时钟,在时钟定时器到时的时候,用信号向程序报告。alarm()系统调用在 Linux 系统函数库 unistd.h 中的函数声明如下: unsigned int alarm(unsigned int seconds); 函数唯一的参数是 seconds ,其以秒为单位给出了定时器的时间。当时间到达的时候, 就向系统发送一个 SIGARLM 信号。例如: alarm(60); 这一调用实现在 60 秒后发一个 SIGALRM 信号。alarm 不会象 sleep 那样暂停调用进 程的执行,它能立即返回,并使进程继续执行,直至指定的延迟时间到达发出 SIGALRM 信号。事实上,一个由 alarm()调用设置好的报警时钟,在通过 exec() 调用后,仍将继续有 效。但是,它在 fork() 调用后中,在子进程中失效。 如果要使设置的报警时钟失效,只需要调用参数为零的 alarm(): alarm(0) alarm()调用也不能积累。如果调用 alarm 两次,则第二次调用就取代第一次调用。但 是,后一个alarm会把前一个alarm的剩余时间作为返回值,然后自己重新从0开始计数,前一个alarm就此成为历史。 当需要对某项工作设置时间限制时,可以使用 alarm()调用来实现。其基本方法为:先 调用 alarm()按时间限制值设置报警时钟,然后进程作某一工作。如果进程在规定时间以内 完成这一工作,就再调用 alarm(0)使报警时钟失效。如果在规定时间内未能完成这一工作, 进程就会被报警时钟的 SIGALRM 信号中断,然后对它进行校正。 下面这个程序使用上述方法来强制用户作出回答。在其中包括一个 quickreply()函数, 它有一个参数 prompt,它是一个指向提示字符串的指针。quickreply 的返回值也是一个指 针。它指向含有输入行信息的字符串。这个例行程序在试作五次之后,如果仍未得到输入 信息,就返回一个 null 指针。每当 quickreply 要提醒用户时,它就向终端发送 ASCII 码 007,这会使终端响铃。quickreply 调用了标准 I/O 库中的例行程序 gets()。gets()把标准输入上的下一行信息存入一个字符型数组,它返回一个指向该数组的指针。当到达文件末或出错时,gets 则返回一个 null 指针。函数 catch 是信号 SIGALRM 的关联函数,它完成对此信号的处理。catch设置了一个 timed_out 标志,在 quickreply 中对这个标志进行检查,看它是否超过了规定的时限。 #include <stdio.h> #include <signal.h> #define TIMEOUT 5 #define MAXTRIES 5 #define LINESIZE 100 #define BELL '\007' #define TRUE 1 #define FALSE 0 /* 判断超时是否已经发生的标志*/ static int time_out; static char inputline[LINESIZE]; char* quickreply (char* prompt); - 60- Linux 网络编程 main() { printf("%s\n",quickreply("Input")); } char* quickreply (char* prompt) { int (*was)(),catch(),ntries; char* answer; /* 设定捕捉 SIGALRM 的的关联并保存原有关联*/ was=signal(SIGALRM,catch); for (ntries=0;ntries<MAXTRIES;ntries++) { time_out=FALSE; printf("\n%s>",prompt); /* 设定定时器*/ alarm(TIMEOUT); /* 获取输入*/ answer=gets(inputline); /* 关闭定时器*/ alarm(0); if (!time_out) break; } /* 恢复原有的 SIGALRM 关联*/ signal(SIGALRM,was); return (time_out?((char*) 0):answer); } /* SIGALRM 信号处理函数*/ catch() { /* 设定超时标志*/ time_out=TRUE; /* 响铃警告*/ putchar(BELL); } 2.系统调用 pause() 系统调用 pause()能使调用进程暂停执行,直至接收到某种信号为止。pause()在 Linux 系统函数库 unistd.h 中的函数声明如下: int pause(void); 该调用没有任何的参数。它的返回始终是 -1 ,此时 errno 被设置为ERESTARTNOHAND 。 下面这个程序为了在规定时间显示一个消息,使用了 alarm 和 pause。对它的调用方法 如下: $tml minutes message-text & 第一个参数为时间数,第二个参数为显示的消息。 #include <stdio.h> #include <signal.h> #define TRUE 1 #define FALSE 0 #define BELLS "\007\007\007" int alarm_flag=FALSE; /* SIGALRM 处理函数*/ setflag() { alarm_flag=TRUE; } main(int argc,char* argv[]) { int nsecs; int i; if (argc<2) { fprintf(stderr,"Usage:tml #minutes message\n"); exit(1); } if ((nsecs=atoi(argv[1])*60)<=0) { fprintf(stderr,"Invalid time\n"); exit(2); } /* 设定 SIGALRM 的关联动作*/ signal(SIGALRM,setflag); - 62- Linux 网络编程 /* 设定定时器*/ alarm(nsecs); /*使用 pause()调用等待信号*/ pause(); if (alarm_flag) { printf(BELLS); for (i=2;i<argc;i++) { printf("%s\n",argv[i]); } } exit(0); }
    展开阅读全文
    提示  咨信网温馨提示:
    1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
    2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
    3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
    4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
    5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
    6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

    开通VIP折扣优惠下载文档

    自信AI创作助手
    关于本文
    本文标题:linux信号与系统调用的关系.doc
    链接地址:https://www.zixin.com.cn/doc/8750317.html
    页脚通栏广告

    Copyright ©2010-2025   All Rights Reserved  宁波自信网络信息技术有限公司 版权所有   |  客服电话:0574-28810668    微信客服:咨信网客服    投诉电话:18658249818   

    违法和不良信息举报邮箱:help@zixin.com.cn    文档合作和网站合作邮箱:fuwu@zixin.com.cn    意见反馈和侵权处理邮箱:1219186828@qq.com   | 证照中心

    12321jubao.png12321网络举报中心 电话:010-12321  jubao.png中国互联网举报中心 电话:12377   gongan.png浙公网安备33021202000488号  icp.png浙ICP备2021020529号-1 浙B2-20240490   


    关注我们 :微信公众号  抖音  微博  LOFTER               

    自信网络  |  ZixinNetwork