加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱制作网_池州站长网 (https://www.0566zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

第11章 UNIX进程之间的通信

发布时间:2022-12-21 10:59:25 所属栏目:Unix 来源:
导读:  UNIX进程间的通信机制用于解决进程之间的信息交换和协调彼此的推进速度。 UNIX系统的进程通信包括管道、 消息缓冲、 共享主存和信号量机制。11.1管道通信(pipes) 管道通信是借助于文件使进程之间按先进先出管道通
  UNIX进程间的通信机制用于解决进程之间的信息交换和协调彼此的推进速度。 UNIX系统的进程通信包括管道、 消息缓冲、 共享主存和信号量机制。11.1管道通信(pipes) 管道通信是借助于文件使进程之间按先进先出管道通信是借助于文件使进程之间按先进先出方式同步传递数据的一种形式。有两种类型的管道: 无名管道(pipes)和有名管道(FIFO)。无名管道用于父子或两兄弟进程之间以FIFO规则传递信息。 管道必须由父进程创建。有名管道(FIFO)通常用于实现不要求具有父子关系的进程之间传输大量的信息。第第1111章章 UNIXUNIX进程之间的通信进程之间的通信管道文件是一个临时文件, 通信完成,文件就不再存在。管道通信方式是: 一个进程用write命令向管道写入数据, 另一个进程用read命令读管道中的数据。读、 写必需同步。一一、 、 创建无名管道创建无名管道(pipe)(pipe)的系统调用当同族进程之间需要通过管道进行通信时, 调用系统调用pipe() 建立一个无名管道。 其调用语法如下:pipe(fdp)这里, fdp是一个指针数组。 纪录对管道读写的两个文件描述符。的系统调用其实现过程是:① 在管道文件所在的设备上分配一个i节点, 并在主存分配一个活动i节点, 其文件类型为IFIFO。
 
  ② 为调用进程在系统打开文件表中分配两个表项, 分别用FREAD和FWRITE填写, 以指示对管道的读和写指示对管道的读和写, 并使f_inode指向内存I节点。 同时在用户打开文件表中开辟两个表项分别指向系统打开文件表的两个表项。③为 pipe 文 件 的 主 存 i 节 点 置 初值: I_count=2, I_frcnt=1; I_fwcnt=1。④将文件描述符通过数组fdp返回给调用进程。并使f id 指向内pipe文件没有路径名, 它是由pipe文件所在设备上的i节点、 与之对应的主存i节点、两个系统打开文件表项及要求生成pipe文件的进程打开文件表的两个表项组成。开始时, 该文件的长度为0, 是一个空白文件。 pipe文件生成时的数据结构如下图所示。用户打开文件表索引节点文件表内存索引节点表外存pipe文件pf0fpd0fpd1……………………pf1I节点指针I节点指针对pipe文件大小的限制: pipe文件只使用索引节点中的直接地址项, 其长度被限制为10个盘块大小。 核心将直接地址项作为一个循环队列来管理, 而将读指针(I_frptr)、 写指针(I_fwptr)、 读管道的进程数(I_frcnt)、 写管道进程的数(I_fwcnt)及等待使用标志(I_fflag)等信息放入剩下的3个索引项中, 并按先进先出顺序进行读和写。
 
  进程互斥: 诸进程互斥访问pipe文件索引节点中的直接地址项。 加一把锁。之后创建一个或几个子进程。 此时, 子进程复制父进程的用户 打开文件表, 于是pipe文件就为父、 子进程(或同族进程之间)共享。 之后, 各进程分别关闭掉pipe文件的发送端与接收端, 通过调用READ() 或WRITE()函数对pipe文件进行存取。为了 避免混乱一个pipe文件最好为两为了 避免混乱, 一个pipe文件最好为两进程专用, 一个用于读, 一个用于写。 这样,结果形成如图11. 2(p227) 所示的结构。通信完成后, 使用关闭命令CLOSE(),将其关闭, 收回文件占用的系统全部资源。文件一经关闭, 不再存在。二、创建一个有名管道(named pipe)无名管道是一个临时文件, 当文件被关闭后,文件就不复存在, 且只能用于同族进程之间的通信。UNIX系统V提供了 有名管道, 实现非同族进程之间的通信。 有名管道可用于同一机器进程间的本地通信, 也可用于通过网络连接的不同机器进程间的通信调用语法如下间的通信。 调用语法如下:mknod(pathname, mode, dev)其中pathname是新创建的有名管道的文件路径名, mode是被创建文件的类型和存取方式, dev是文件所在的设备。
 
  有名管道被创建后, 在系统中有一个目录项和对应的外存i节点与之对应, 但并不将它打开。 只要这种文件不删除, 它与普通文件一样永久存在, 只是文件长度为零。2打开一个有名管道由于有名管道创建时并没有打开由于有名管道创建时并没有打开, 因此必须显式地使用如下的打开系统调用将文件打开。open(pathname, oflg)其中pathname是要打开的有名管道的路径名, oflg是文件打开时的存取方式。因此必通信的发送者以O_WRONLY只写方式、 接收方以O_RDONLY只读方式打开有名管道。有名管道打开后通信双方使用读写命令进行通信, 通信完成后就立即关闭。 有名管道文件关闭后, 它所占用的磁盘块全部释放,但文件仍占有一个目录项和一个I节点。 只但文件仍占有个目录项和是文件长度为0。进程间使用有名管道实现通信时,必须有三次同步。个I节点。 只第一次是打开同步。当一个进程以读方式打开有名管道时unix进程通信, 若已有写者打开过, 则唤醒写者后继续前进, 否则, 睡眠等待写者。当一个进程以写方式打开有名管道时, 若已有读者打开过, 则唤醒读者继续前则睡后继续前进。 否则睡眠等待读者。第二次是读写同步。
 
  同步方式与pipe相同。 允许写者超前读者1024个字符。 当写者写时, 检查有无读者等待, 若有, 唤醒后, 再写。当管道被写满时, 写者必须睡眠等待。等待读读者从有名管道读时, 若没有数据可读, 则睡眠等待。 若有数据可读, 读完后要检查有无写者等待, 若有唤醒写者。读写两方必须随时检查通信的另一方是否还存在, 一旦有一方不存在, 应立即终止通信过程。第三次是关闭同步。当一个写进程关闭有名管道时, 若发现有进程睡眠等待从管道读, 则唤醒它,被唤醒进程立即从读调用返回。当一个读进程关闭有名管道时, 若发现有进程睡眠等待向管道写, 则唤醒它,并向它发一个指示错误条件的信号后返回。最后一个关闭有名管道的进程, 释放该管道占用的全部盘块及相应主存i节点。举例:例1父子进程之间采用无名管道通信char parent[ ] = “A message from parent. \ n”main(){int chan1[2] ;hb[100]char buf[100] ;pipe(chan1) ;if(fork() ){ close(chan1[0] ) ; / *父进程关闭读通道*/write(chan1[1] , parent, sizeof(parent) ) ;close(chan1[1] ) ;print(“parent process terminates\ n”) ;}else{close(chan1[1] ) ; / *子进程关闭写通道*/read(chan1[0] , buf, 100) ;printf(“child process read: : %s\ n”, buf) ;close(chan1[0] ) ;printf(“child process terminates\ n”) ;}}例2例2任意两进程之间通过#includechar string[] =“a”;main(argc, argv)int argc;char *argv[] ;{ int fd;char buf[256] ;任意两进程之间通过一个有名管道通信个有名管道通信mknod(“fifo”, 010777, 0) ; / *以读写执行方式为所有用户创建有名管道*/if(argc==2)fd=open(“fifo”, O_WRONLY) ;/ *通信发送方用只写方式打开*/elsefd=open(“fifo”, O_RDONLY) ;/ *通信接收方用只读方式打开*/信接收方用只读方式打开for(, , )if(argc==2)write(fd, string, 2) ;printf(“\n I have wrote : %s”, string) ;string[0] +=1;close(fd) ;elseRead(fd, buf, 6) ;printf(“\n I have read : ”, buf) ;buf[0] =‘\0’ ;close(fd) ;}有名管道程序的运行方式有名管道程序的运行方式:一个进程用“./a.exe 1&” 命令行在后台运行;另一个进程用“ ./a.exe”命令行在前台运行。
 
  2 2、 消息缓冲机制、 消息缓冲机制消息: 是一个格式化的可变长的信息单元。 在UNIX中, 消息机制向用户提供了四个系统调用。消息机制的数据结构:消息首部记录消息的类型– 消息首部: 记录消息的类型、 大小、 指向消息数据区的指针、 消息队列的连接指针等。– 消息队列头表: 包含了指向消息队列中第一个消息的指针和指向最后一个消息的指针、 队列中消息的数目、 队列中消息数据的总字节数、队列所允许的消息数据的最大字节总数等。大小指向消息消息首部消息首部消息首部消息缓冲区消息缓冲区消息缓冲区队列i消息队列头表…012…消息缓冲区消息首部队列n…消息队列中的数据结构? 建立一消息队列:int msgget(key,msgflg); key_t key; 用户指定的消息队列的名字int msgflg; 用户设置的标志和访问方式返回一个消息队列描述符? 消息的发送:消息的发int msgsnd(msgid, msgp,msgsz,msgflg);int msgid; 消息队列描述符struct msgbuf * msgp;指向消息缓冲区的指针int msgsz; 消息的长度int msgflg; 当无内存空间存储消息时, 等待? 放回?? 消息的接收:int msgrev(msgid,msgp,msgsz,msgtpy,msgflg);int msgid,msgsz,msgflg;struct msgbuf * msgp;long msgtpy; 规定选读的消息类型? 消息队列的操纵: 如读出状态信息并修改int msgctl(msgid,cmd,buf);int msgid,cmd; cmd是规定的命令struct msgid_ds * buf; 存放控制参数和查询结果。
 

(编辑:我爱制作网_池州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章