进程之间的通信Word格式.docx

上传人:b****3 文档编号:8320036 上传时间:2023-05-11 格式:DOCX 页数:12 大小:832.65KB
下载 相关 举报
进程之间的通信Word格式.docx_第1页
第1页 / 共12页
进程之间的通信Word格式.docx_第2页
第2页 / 共12页
进程之间的通信Word格式.docx_第3页
第3页 / 共12页
进程之间的通信Word格式.docx_第4页
第4页 / 共12页
进程之间的通信Word格式.docx_第5页
第5页 / 共12页
进程之间的通信Word格式.docx_第6页
第6页 / 共12页
进程之间的通信Word格式.docx_第7页
第7页 / 共12页
进程之间的通信Word格式.docx_第8页
第8页 / 共12页
进程之间的通信Word格式.docx_第9页
第9页 / 共12页
进程之间的通信Word格式.docx_第10页
第10页 / 共12页
进程之间的通信Word格式.docx_第11页
第11页 / 共12页
进程之间的通信Word格式.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

进程之间的通信Word格式.docx

《进程之间的通信Word格式.docx》由会员分享,可在线阅读,更多相关《进程之间的通信Word格式.docx(12页珍藏版)》请在冰点文库上搜索。

进程之间的通信Word格式.docx

(1)pipe()函数调用格式如下:

#include<

unistd.h>

intpipe(intfdes[2]);

参数:

fdes[2]数组存放返回的两个文件描述符。

返回值:

正确返回0,错误返回-1。

使用无名管道通信时,是使用临时文件的方式实现进程之间的批量数据传输。

若通信双方不是父子关系,不能直接建立通信联系。

必须由父进程先创建一个管道,再创建需要通信的两个子进程,两者是通过复制父进程映像使两者建立联系的。

(2)无名管道pipe()的使用示例

2、popen()和pclose()函数

系统提供了创建管道的简单函数popen()和pclose()。

当使用这两个函数对管道操作时,所有复杂的操作,如创建管道、fork()子进程、关闭管道的无用端,执行一个shell命令,等待命令执行完成后返回等操作都在系统内部自动完成。

(1)popen()和pclose()函数的调用格式如下:

stdio.h>

FILEpopen(constcharcmdstring,constchar*open_mode);

intpclose(FILE*fp);

其中,cmdstring是shell要求的包括参数和选项的一个完整的命令行。

open_mode指出管道访问方式:

读(“r”)或写(“w”)。

返回值:

popen()函数正确返回文件结构的指针,错误返回空指针NULL;

pclose()函数正确返回cmdstring结束时的退出状态,错误返回-1。

popen()函数先执行fork()函数创建一个子进程,然后调用exec()函数执行命令cmdstring,并且返回一个标准I/O文件指针。

若open_mode为“r”,那么管道的输入端与命令行cmdstring的标准输出端相连,即父进程以“r”方式打开管道并成功获得管道文件的指针,用于从管道读。

被创建的子进程执行cmdstring命令行,向管道输出,具体可见下图1所示若open_mode为“w”,那么管道的输出端与命令行cmdstring的标准输入端相连,即父进程以“w”方式打开管道并成功地获得管道文件的指针,用于向管道写,被创建的子进程从管道读入,以完成命令行的执行,如图2所示。

以命令行为参数的管道文件的示例。

二、有名管道的通信

1、创建一个有名管道的系统调用mkdfifo()

有名管道的使用方式与无名管道不同。

有名管道可被任何知道其名字的进程打开和使用。

为了使用有名管道,进程要先建立它,并与它的一端相连,创建有名管道的进程叫服务器进程,存取管道的其他进程叫客户进程。

通信双方必须首先创建有名管道后,才能打开进行读写。

当文件不再需要时,要显式删除。

调用格式如下:

#include<

sys/types.h>

sys/stat.h>

fcntl.h>

intmknod(constchar*pathname,mode_tmode,dev_tdev);

intmkfifo(constchar*pathname,mode_tmode);

其中pathname是新创建的有名管道的文件路径名,mode是被创建文件的类型和存取方式,dev是文件所在的设备。

对于有名管道,dev这个参数是0。

这两个系统调用隐含指定以“O_CREAT|O_EXCL”方式,创建一个新的FIFO文件。

返回值:

成功时,返回0;

不成功时(即文件已经存在),返回-1。

2、打开一个有名管道

由于有名管道创建时并没有打开,因此必须显式地使用如下的系统调用将文件打开:

open(pathname,oflg);

其中,pathname是要打开的有名管道的路径名,oflg是文件打开时的存取方式。

打开一个有名管道与一个普通文件没有区别,只是通信的发送者以OWRONLY只写方式、接收方以ORDONLY只读方式打开。

进程间使用有名管道实现通信时,必须有三次同步:

第一次是打开同步。

当一个进程以读方式打开有名管道时,若已有写者打开过,则唤醒写者后继续前进,否则,睡眠等待写者。

当一个进程以写方式打开有名管道时,若已有读者打开过,则唤醒读者后继续前进,否则等待读者。

第二次是读写同步。

其同步方式与pipe相同,运行写者超前读者1024个字符。

当一次写超过1024时,超过的字符要写入时,则写者必须等待。

读者从有名管道读时,若没有数据可读则等待。

若有数据可读,读完后要检查有无写者等待,若有唤醒写者。

而且要求读写两方要随时检查通信的另一方是否还存在,一旦有一方不存在,应立即终止通信过程。

第三次是关闭同步。

当一个写进程关闭有名管道时,若发现有进程睡眠等待从管道读,则唤醒它,被唤醒进程立即从读调用返回。

当一个读进程关闭有名管道时,若发现有进程睡眠等待向管道写,则唤醒它,并向它发一个指示错误条件的信号后返回。

最后一个关闭有名管道的基础,释放该管道占用的全部盘块及相应主存i节点。

有名管道打开后,就可以使用文件的读写命令进行读写,读写完成后就立即关闭。

有名管道文件关闭后,文件本身并没有消失。

有名管道的读、写和关闭动作与普通玩家完全相同。

有名管道的使用示例

习题:

编写一个有名管道程序。

一个(客户)进程从键盘循环读一系列字符,将这些字符和发送者的pid发给服务器进程,让其统计输入的是字符还是数字,分别为多少个,完成后再向客户进程发回服务的结果,由客户进程输出

4.源代码

stdarg.h>

#defineCLIENT2

#defineMAX_BUF2000

intmain(intargc,char*argv[])

{

mkfifo("

server"

010777,0);

client"

charbuf[MAX_BUF];

if(argc==CLIENT)

printf("

clienthasbeguntorun!

\n"

);

freopen("

./input.txt"

"

r"

stdin);

clienthasopenedinput.txt\n"

intfd;

clientiswaitingfortheservertofireup...\n"

fd=open("

O_WRONLY);

clienthasopenedtheserverpipe\n"

intid=getpid();

clienthasgotpid=%d.\n"

id);

sprintf(buf,"

%d"

clienthaswrittenpidtobuf\n"

gets(buf+strlen(buf));

clienthasappendinputdatatobuf\n"

write(fd,buf,sizeof(buf));

clientwirttendata=%stopipe.\n"

buf);

close(fd);

O_RDONLY);

clienthasopenedtheclientpipe\n"

read(fd,buf,sizeof(buf));

clienthasgottheresultfromserver\n"

%s\n"

}

else

serveriswaitingfortheclienttofireup...\n"

serverhasopenedtheserverpipe\n"

serverhasgotdata=%s\n"

intid;

sscanf(buf,"

%d"

&

id);

serverhasgotthepid=%d\n"

char*p=buf;

while(*p&

&

*p!

='

'

)p++;

serverisgoingtopasetheleftdata=%s\n"

p);

charc;

intnum=0,alph=0;

while(c=*p)

{

if('

0'

<

=c&

c<

9'

num++;

elseif('

a'

z'

||'

A'

Z'

alph++;

serverhasgotdata=%c\n"

c);

p++;

}

serverhasopenedtheclientpipe\n"

Inputfrompidof%dwith%dnumbersand%dalphabets\n"

id,num,alph);

serverhassendtheresulttoclient\n"

return0;

5.运行效果

cgrambler@ubuntu:

~/cgr$gcc-ompipempipe.c

mpipe.c:

Infunction‘main’:

44:

warning:

incompatibleimplicitdeclarationofbuilt-infunction‘strlen’

/tmp/ccikCWwT.o:

Infunction`main'

:

(.text+0x12c):

the`gets'

functionisdangerousandshouldnotbeused.

~/cgr$./mpipe1&

[1]2698

~/cgr$clienthasbeguntorun!

clienthasopenedinput.txt

clientiswaitingfortheservertofireup...

clienthasopenedtheserverpipe

clienthasgotpid=2698.

clienthaswrittenpidtobuf

clienthasappendinputdatatobuf

clientwirttendata=2698abc123topipe.

clienthasopenedtheclientpipe

clienthasgottheresultfromserver

Inputfrompidof2698with3numbersand3alphabets

~/cgr$./mpipe

serveriswaitingfortheclienttofireup...

serverhasopenedtheserverpipe

serverhasgotdata=2698abc123

serverhasgotthepid=2698

serverisgoingtopasetheleftdata=abc123

serverhasgotdata=

serverhasgotdata=a

serverhasgotdata=b

serverhasgotdata=c

serverhasgotdata=1

serverhasgotdata=2

serverhasgotdata=3

serverhasopenedtheclientpipe

serverhassendtheresulttoclie*[

6.实验体会

通过这次实验,我加深了能Linux进程通信,特别是有名管道的理解。

管道是半双工的,数据只能向一个方向流动;

需要双方通信时,需要建立起两个管道;

只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

单独构成一种独立的文件系统:

管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。

数据的读出和写入:

一个进程向管道中写的内容被管道另一端的进程读出。

写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(namedpipe或FIFO)提出后,该限制得到了克服。

FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。

这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。

值得注意的是,FIFO严格遵循先进先出(firstinfirstout),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。

它们不支持诸如lseek()等文件定位操作。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2