当前位置: 首页 > news >正文

聊城网站建设lchckj网站建设一般需要多少钱

聊城网站建设lchckj,网站建设一般需要多少钱,医院网站改版建设方案,徐州市建设工程前言 本期我们来学习进程间的通讯 一、信号机制 1、信号的基本概念 每个信号都对应一个正整数常量(称为signal number,即信号编号。定义在系统头文件signal.h中)#xff0c;代表同一用户的诸进程之间传送事先约定的信息的类型#xff0c;用于通知某进程发生了某异常…前言 本期我们来学习进程间的通讯 一、信号机制 1、信号的基本概念 每个信号都对应一个正整数常量(称为signal  number,即信号编号。定义在系统头文件signal.h中)代表同一用户的诸进程之间传送事先约定的信息的类型用于通知某进程发生了某异常事件。每个进程在运行时都要通过信号机制来检查是否有信号到达。若有便中断正在执行的程序转向与该信号相对应的处理程序以完成对该事件的处理处理结束后再返回到原来的断点继续执行。实质上信号机制是对中断机制的一种模拟故在早期的UNIX版本中又把它称为软中断。 信号与中断的相似点 1采用了相同的异步通信方式 2当检测出有信号或中断请求时都暂停正在执行的程序而转去执行相应的处理程序 3都在处理完毕后返回到原来的断点 4对信号或中断都可进行屏蔽。 信号与中断的区别 1中断有优先级而信号没有优先级所有的信号都是平等的 2信号处理程序是在用户态下运行的而中断处理程序是在核心态下运行 3中断响应是及时的而信号响应通常都有较大的时间延迟。 信号机制具有以下三方面的功能 1发送信号。发送信号的程序用系统调用kill( )实现 2预置对信号的处理方式。接收信号的程序用signal( )来实现对处理方式的预置 3收受信号的进程按事先的规定完成对相应事件的处理。 2、信号的发送 信号的发送是指由发送进程把信号送到指定进程的信号域的某一位上。如果目标进程正在一个可被中断的优先级上睡眠核心便将它唤醒发送进程就此结束。一个进程可能在其信号域中有多个位被置位代表有多种类型的信号到达但对于一类信号进程却只能记住其中的某一个。 进程用kill( )向一个进程或一组进程发送一个信号。 3、对信号的处理 当一个进程要进入或退出一个低优先级睡眠状态时或一个进程即将从核心态返回用户态时核心都要检查该进程是否已收到软中断。当进程处于核心态时即使收到软中断也不予理睬只有当它返回到用户态后才处理软中断信号。对软中断信号的处理分三种情况进行 1如果进程收到的软中断是一个已决定要忽略的信号function1进程不做任何处理便立即返回 2进程收到软中断后便退出function0 3执行用户设置的软中断处理程序。 4、所涉及的中断调用 1kill( )函数 系统调用格式 int  kill(pid,sig) 参数定义int  pid,sig; 其中pid是一个或一组进程的标识符参数sig是要发送的软中断信号。 1pid0时核心将信号发送给进程pid。 2pid0时核心将信号发送给与发送进程同组的所有进程。 3pid-1时核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。 2signal( )函数 功能重置对信号的处理方式允许调用进程控制软中断信号。 系统调用格式 signal(sig,function) 头文件为                  #include signal.h 参数定义 signal(sig,function) int  sig; void (*func) ( ) 其中sig用于指定信号的类型sig为0则表示没有收到任何信号余者如下表 值 名  字 说          明 01 SIGHUP 挂起hangup 02 SIGINT 中断当用户从键盘按^c键或^break键时 03 SIGQUIT 退出当用户从键盘按quit键时 04 SIGILL 非法指令 05 SIGTRAP 跟踪陷阱trace trap启动进程跟踪代码的执行 06 SIGIOT IOT指令 07 SIGEMT EMT指令 08 SIGFPE 浮点运算溢出 09 SIGKILL 杀死、终止进程 10 SIGBUS 总线错误 11 SIGSEGV 段违例segmentation  violation进程试图去访问其虚地址空间以外的位置 12 SIGSYS 系统调用中参数错如系统调用号非法 13 SIGPIPE 向某个非读管道中写入数据 14 SIGALRM 闹钟。当某进程希望在某时间后接收信号时发此信号 15 SIGTERM 软件终止software  termination 16 SIGUSR1 用户自定义信号1 17 SIGUSR2 用户自定义信号2 18 SIGCLD 某个子进程死 19 SIGPWR 电源故障 function在该进程中的一个函数地址在核心返回用户态时它以软中断信号的序号作为参数调用该函数对除了信号SIGKILLSIGTRAP和SIGPWR以外的信号核心自动地重新设置软中断信号处理程序的值为SIG_DFL一个进程不能捕获SIGKILL信号。 function 的解释如下 1function1时进程对sig类信号不予理睬亦即屏蔽了该类信号 2function0时缺省值进程在收到sig信号后应终止自己 3function为非0非1类整数时function的值即作为信号处理程序的指针。 #include stdio.h #include signal.h #include unistd.h #includestdlib.h #include sys/wait.h void waiting(), stop(); int wait_mark; int main() {int p1, p2, stdout;while ((p1 fork()) -1); /*创建子进程p1*/if (p1 0){while ((p2 fork()) -1); /*创建子进程p2*/if (p2 0){wait_mark 1;signal(SIGINT, stop); /*接收到^c信号转stop*/waiting();kill(p1, 16); /*向p1发软中断信号16*/kill(p2, 17); /*向p2发软中断信号17*/wait(0); /*同步*/wait(0);printf(Parent process is killed!\n);exit(0);}else{wait_mark 1;signal(17, stop); /*接收到软中断信号17转stop*/waiting();lockf(stdout, 1, 0);printf(Child process 2 is killed by parent!\n);lockf(stdout, 0, 0);exit(0);}}else{wait_mark 1;signal(16, stop); /*接收到软中断信号16转stop*/waiting();lockf(stdout, 1, 0);printf(Child process 1 is killed by parent!\n);lockf(stdout, 0, 0);exit(0);} }void waiting() {while (wait_mark ! 0); }void stop() {wait_mark 0; } 输出结果 屏幕上无反应按下^C后显示  Parent  process  is  killed!  如图所示 原因分析 全部进程都收到终止信号父进程重置了SIGINT,信号而子进程没有重置所以会被kill掉。 上述程序中signal( )都放在一段程序的前面部位而不是在其他接收信号处。这是因为signal( )的执行只是为进程指定信号值16或17的作用以及分配相应的与stop( )过程链接的指针。因而signal( )函数必须在程序前面部分执行。  二、进程管道通信 1、什么是管道 UNIX系统在OS的发展上最重要的贡献之一便是该系统首创了管道pipe。这也是UNIX系统的一大特色。         所谓管道是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件又称为pipe文件。由写进程从管道的写入端句柄1将数据写入管道而读进程则从管道的读出端句柄0读出数据。 2、管道的类型 1有名管道 一个可以在文件系统中长期存在的、具有路径名的文件。用系统调用mkfifo( )建立。它克服无名管道使用上的局限性可让更多的进程也能利用管道进行通信。因而其它进程可以知道它的存在并能利用路径名来访问该文件。对有名管道的访问方式与访问其他文件一样需先用open( )打开。 2无名管道 一个临时文件。利用pipe( )建立起来的无名文件无路径名。只用该系统调用所返回的文件描述符来标识该文件故只有调用pipe( )的进程及其子孙进程才能识别此文件描述符才能利用该文件管道进行通信。当这些进程不再使用此管道时核心收回其索引结点。 二种管道的读写方式是相同的本文只讲无名管道。 3pipe文件的建立 分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符 4读/写进程互斥 内核为地址设置一个读指针和一个写指针按先进先出顺序读、写。         为使读、写进程互斥地访问pipe文件需使各进程互斥地访问pipe文件索引结点中的直接地址项。因此每次进程在访问pipe文件前都需检查该索引文件是否已被上锁。若是进程便睡眠等待否则将其上锁进行读/写。操作结束后解锁并唤醒因该索引结点上锁而睡眠的进程。 3、所涉及的系统调用     1pipe( ) 功能建立一无名管道。 系统调用格式               pipe(filedes) 参数定义 int  pipe(filedes); int  filedes[2]; 其中filedes[1]是写入端filedes[0]是读出端。 该函数使用头文件如下 #include unistd.h #inlcude signal.h #include stdio.h 2read( ) 系统调用格式                   read(fd,buf,nbyte) 功能从fd所指示的文件中读出nbyte个字节的数据并将它们送至由指针buf所指示的缓冲区中。如该文件被加锁等待直到锁打开为止。 参数定义 int  read(fd,buf,nbyte); int  fd; char *buf; unsigned  nbyte; 3write( ) 系统调用格式                   write(fd,buf,nbyte) 功能把nbyte 个字节的数据从buf所指向的缓冲区写到由fd所指向的文件中。如文件加锁暂停写入直至开锁。 参数定义同read( )。 参考示例 #includestdio.h #includeunistd.h #includestdlib.h #include sys/wait.h #include signal.h int pid1, pid2;int main() {int fd[2];char outpipe[100], inpipe[100];pipe(fd); /*创建一个管道*/while ((pid1 fork()) -1);if (pid1 0){lockf(fd[1], 1, 0);sprintf(outpipe, child 1 process is sending message!);/*把串放入数组outpipe中*/write(fd[1], outpipe, 50); /*向管道写长为50字节的串*/sleep(5); /*自我阻塞5秒*/lockf(fd[1], 0, 0);exit(0);}else{while ((pid2 fork()) -1);if (pid2 0){lockf(fd[1], 1, 0);/*互斥*/sprintf(outpipe, child 2 process is sending message!);write(fd[1], outpipe, 50);sleep(5);lockf(fd[1], 0, 0);exit(0);}else{wait(0); /*同步*/read(fd[0], inpipe, 50); /*从管道中读长为50字节的串*/printf(%s\n, inpipe);wait(0);read(fd[0], inpipe, 50);printf(%s\n, inpipe);exit(0);}} } 输出结果  延迟5秒后显示child 2 process is sending message! 再延迟5秒显示child 1 process is sending message! child 1 和child 2 的显示顺序是变化的因为这个是并发输出的。 三、消息发送与接收 一、什么是消息 消息message是一个格式化的可变长的信息单元。消息机制允许由一个进程给其它任意的进程发送一个消息。当一个进程收到多个消息时可将它们排成一个消息队列。消息使用二种重要的数据结构一是消息首部其中记录了一些与消息有关的信息如消息数据的字节数二个消息队列头表其每一表项是作为一个消息队列的消息头记录了消息队列的有关信息。 1、消息机制的数据结构 1消息首部 记录一些与消息有关的信息如消息的类型、大小、指向消息数据区的指针、消息队列的链接指针等。 2消息队列头表 其每一项作为一个消息队列的消息头记录了消息队列的有关信息如指向消息队列中第一个消息和指向最后一个消息的指针、队列中消息的数目、队列中消息数据的总字节数、队列所允许消息数据的最大字节总数还有最近一次执行发送操作的进程标识符和时间、最近一次执行接收操作的进程标识符和时间等。 2、消息队列的描述符 UNIX中每一个消息队列都有一个称为关键字key的名字是由用户指定的消息队列有一消息队列描述符其作用与用户文件描述符一样也是为了方便用户和系统对消息队列的访问。 二、涉及的系统调用 1. msgget( ) 功能打开或创建一个消息队列获得一个消息队列的描述符。核心将搜索消息队列头表确定是否有指定名字的消息队列。若无核心将分配一新的消息队列头并对它进行初始化然后给用户返回一个消息队列描述符否则它只是检查消息队列的许可权便返回。 系统调用格式 msgqidmsgget(key,flag) 该函数使用头文件如下 #includesys/types.h #includesys/ipc.h #includesys/msg.h 参数定义 int msgget(key,flag) key_t  key; int  flag; 其中 key是用户指定的消息队列的名字flag是用户设置的标志和访问方式。如  IPC_CREAT |0400       是否该队列已被创建。无则创建是则打开 IPC_EXCL |0400        是否该队列的创建应是互斥的。 msgqid 是该系统调用返回的描述符失败则返回-1。 2. msgsnd 功能发送一消息。向指定的消息队列发送一个消息并将该消息链接到该消息队列的尾部。 系统调用格式 msgsnd(msgqid,msgp,size,flag) 该函数使用头文件如下 #include sys/types.h #include sys/ipc.h #include sys/msg.h 参数定义 int msgsnd(msgqid,msgp,size,flag) I   int msgqid,size,flag; struct msgbuf  * msgp; 其中msgqid是返回消息队列的描述符msgp是指向用户消息缓冲区的一个结构体指针。缓冲区中包括消息类型和消息正文即 { long  mtype;             /*消息类型*/ char  mtext[ ];           /*消息的文本*/ } size指示由msgp指向的数据结构中字符数组的长度即消息的长度。这个数组的最大值由MSG-MAX( )系统可调用参数来确定。flag规定当核心用尽内部缓冲空间时应执行的动作:进程是等待还是立即返回。若在标志flag中未设置IPC_NOWAIT位则当该消息队列中的字节数超过最大值时或系统范围的消息数超过某一最大值时调用msgsnd进程睡眠。若是设置IPC_NOWAIT则在此情况下msgsnd立即返回。 对于msgsnd( )核心须完成以下工作 1对消息队列的描述符和许可权及消息长度等进行检查。若合法才继续执行否则返回 2核心为消息分配消息数据区。将用户消息缓冲区中的消息正文拷贝到消息数据区 3分配消息首部并将它链入消息队列的末尾。在消息首部中须填写消息类型、消息大小和指向消息数据区的指针等数据 4修改消息队列头中的数据如队列中的消息数、字节总数等。最后唤醒等待消息的进程。 3. msgrcv( ) 功能接受一消息。从指定的消息队列中接收指定类型的消息。 系统调用格式 msgrcv(msgqid,msgp,size,type,flag) 本函数使用的头文件如下      #include sys/types.h      #include sys/ipc.h      #include sys/msg.h 参数定义 int  msgrcv(msgqid,msgp,size,type,flag)int  msgqid,size,flag;struct  msgbuf  *msgp;long  type; 其中msgqid,msgp,size,flag与msgsnd中的对应参数相似type是规定要读的消息类型flag规定倘若该队列无消息核心应做的操作。如此时设置了IPC_NOWAIT标志则立即返回若在flag中设置了MS_NOERROR且所接收的消息大于size则核心截断所接收的消息。 对于msgrcv系统调用核心须完成下述工作 1对消息队列的描述符和许可权等进行检查。若合法就往下执行否则返回 2根据type的不同分成三种情况处理 type0接收该队列的第一个消息并将它返回给调用者 type为正整数接收类型type的第一个消息    type为负整数接收小于等于type绝对值的最低类型的第一个消息。 3当所返回消息大小等于或小于用户的请求时核心便将消息正文拷贝到用户区并从消息队列中删除此消息然后唤醒睡眠的发送进程。但如果消息长度比用户要求的大时则做出错返回。 4. msgctl( ) 功能消息队列的操纵。读取消息队列的状态信息并进行修改如查询消息队列描述符、修改它的许可权及删除该队列等。 系统调用格式 msgctl(msgqid,cmd,buf); 本函数使用的头文件如下      #include sys/types.h      #include sys/ipc.h      #include sys/msg.h 参数定义 int msgctl(msgqid,cmd,buf); int  msgqid,cmd; struct  msgqid_ds  *buf; 其中函数调用成功时返回0不成功则返回-1。buf是用户缓冲区地址供用户存放控制参数和查询结果cmd是规定的命令。命令可分三类 1IPC_STAT。查询有关消息队列情况的命令。如查询队列中的消息数目、队列中的最大字节数、最后一个发送消息的进程标识符、发送时间等 2IPC_SET。按buf指向的结构中的值设置和改变有关消息队列属性的命令。如改变消息队列的用户标识符、消息队列的许可权等 3IPC_RMID。消除消息队列的标识符。 msgqid_ds  结构定义如下 struct  msgqid_ds{  struct  ipc_perm  msg_perm;     /*许可权结构*/short  pad1[7];                 /*由系统使用*/ushort msg_qnum;               /*队列上消息数*/ushort msg_qbytes;              /*队列上最大字节数*/ushort msg_lspid;               /*最后发送消息的PID*/ushort msg_lrpid;               /*最后接收消息的PID*/time_t msg_stime;               /*最后发送消息的时间*/time_t msg_rtime;               /*最后接收消息的时间*/time_t msg_ctime;               /*最后更改时间*/};struct  ipc_perm{  ushort uid;                     /*当前用户*/ushort gid;                     /*当前进程组*/ushort cuid;                    /*创建用户*/ushort cgid;                    /*创建进程组*/ushort mode;                   /*存取许可权*/{ short pid1; long pad2;}         /*由系统使用*/  } 5.代码示例 程序说明 1、为了便于操作和观察结果编制二个程序client.c和server.c分别用于消息的发送与接收。 2、server建立一个 Key 为75的消息队列等待其它进程发来的消息。当遇到类型为1的消息则作为结束信号取消该队列并退出server。server每接收到一个消息后显示一句“(server)received。” 3、client使用 key为75的消息队列先后发送类型从10到1的消息然后退出。最后一个消息即是 server端需要的结束信号。client 每发送一条消息后显示一句 “(client)sent”。 4、注意   二个程序分别编辑、编译为client与server。执行 01.服务器server.c 代码用于接收数据 #include sys/types.h #include sys/msg.h #include sys/ipc.h #include unistd.h #include stdio.h #includestdlib.h #define MSGKEY 75 struct msgform {long mtype;char mtext[1000]; }msg; int msgqid;void server() {int i0;msgqid msgget(MSGKEY, 0777 | IPC_CREAT); /*创建75#消息队列*/do{msgrcv(msgqid, msg, 1030, 0, 0); /*接收消息*/printf((server)received\n);} while (msg.mtype ! 1);msgctl(msgqid, IPC_RMID, 0); /*删除消息队列归还资源*/exit(0); }int main() {server(); }02.客户端client.c代码用于发送数据 #include sys/types.h #include sys/msg.h #include sys/ipc.h #includestring.h #include unistd.h #include stdio.h #includestdlib.h #define MSGKEY 75 struct msgform {long mtype;char mtext[1000]; }msg; int msgqid;void client() {int i;msgqid msgget(MSGKEY, 0777); /*打开75#消息队列*/for (i 10; i 1; i--) {msg.mtype i;printf((client)sent\n);msgsnd(msgqid, msg, 1024, 0); /*发送消息*/ }msgsnd(msgqid, msg, 1024, 0); /*发送消息*/exit(0); }int main() {client(); } 输出结果 从理想的结果来说应当是每当client发送一个消息后server接收该消息client再发送下一条。也就是说“(client)sent”和 “(server)received”的字样应该在屏幕上交替出现。实际的结果大多是先由client发送了两条消息然后server接收一条消息。此后client 、server交替发送和接收消息。最后server一次接收两条消息。client 和server 分别发送和接收了10条消息与预期设想一致。如下图所示 下图是client客户端发送的。 下图是server接受端收到的结果。 我们可以去输入ipcs  -q 指令去查看消息队列的情况。如下图所示 这里我们会看到是没有结果的因为接收端收到数据后就删除了消息队列释放空间了所以我们可以在接收端接收数据之前去查看此时的消息队列是存在的结果如下 当然以上程序只是讲了一个方面的知识点你们可以拿到这个代码去稍微修改一下更好的去理解相关的函数功能。 以上就是本期的全部内容了我们下次见 分享一张壁纸
http://www.sadfv.cn/news/58382/

相关文章:

  • 网站开发官网谷歌搜索引擎入口google
  • 淘宝联盟做的好的网站wordpress 导航菜单添加
  • 济南企业做网站推广网站网站建设目的功能
  • 好看的公司网站排版设计衡水安徽网站建设
  • 网站可以做2个公司的吗广州网络建站
  • 东莞南城网站开发公司电话网站开发做前端还是后端
  • 人设生成器网站太原论坛天涯社区
  • 电影网站设计模板制作一个网页的教程
  • 单片机程序员开发网站网站后台密码忘记了
  • 沈阳网站建设开发如何增加网站索引量
  • 网站运营与管理的目的是装潢设计属于什么专业
  • 潍坊 seo网站建设页面设计的像胶囊怎么形容
  • 学设计的网课沧州网站排名优化
  • 文山州住房和城乡建设局网站百度一下首页官网百度
  • 某企业网站建设论文快速建站官网
  • 做网站用的三角形图片有没有免费手游代理
  • 外贸网站运营小程序制作页面教程
  • 环保网站建设维护情况报告吕梁建设机械网站
  • 山东济宁网站建设温州互联网公司
  • 用电脑建设个人网站 并用手机访问seo排名赚app官网
  • 营销型外贸网站建设成都高端响应式网站开发
  • 购物网站建设基本流程树状图网站建设项目需求分析流程
  • 专业建设物流行业网站专业外贸网站建设公司
  • 网站页面优化工具wordpress上传都图片不显示
  • 建设工程竞标网站凡科做网站要钱
  • 园林景观网站源码wordpress 更改数据表
  • 动态ip如何做网站汉中网站建设价格
  • 商城的网站统计如何做公司起名字大全免费测吉凶
  • 网站建设历史安徽博物馆网站建设的调研报告
  • 服务网站设计案例海外互联网推广平台