




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、實(shí)驗(yàn)五 進(jìn)程間通信unix/linux系統(tǒng)的進(jìn)程間通信機(jī)構(gòu)(ipc)允許在任意進(jìn)程間大批量地交換數(shù)據(jù)。本實(shí)驗(yàn)的目的是了解和熟悉linux支持的信號(hào)機(jī)制、管道機(jī)制、消息隊(duì)列通信機(jī)制及共享存儲(chǔ)區(qū)機(jī)制。5.1信號(hào)機(jī)制實(shí)驗(yàn)(一)【實(shí)驗(yàn)?zāi)康摹?了解什么是信號(hào)。2熟悉linux系統(tǒng)中進(jìn)程之間軟中斷通信的基本原理?!緦?shí)驗(yàn)原理】利用signal來(lái)實(shí)現(xiàn)發(fā)送信號(hào)和接受信號(hào)的原理【實(shí)驗(yàn)內(nèi)容】1編寫(xiě)一段程序,使用系統(tǒng)調(diào)用fork( )創(chuàng)建兩個(gè)子進(jìn)程,再用系統(tǒng)調(diào)用signal( )讓父進(jìn)程捕捉鍵盤(pán)上來(lái)的中斷信號(hào)(即按ctrl+c鍵),當(dāng)捕捉到中斷信號(hào)后,父進(jìn)程用系統(tǒng)調(diào)用kill( )向兩個(gè)子進(jìn)程發(fā)出信號(hào),子進(jìn)程捕捉到父
2、進(jìn)程發(fā)來(lái)的信號(hào)后,分別輸出下列信息后終止: child process 1 is killed by parent!child process 2 is killed by parent!父進(jìn)程等待兩個(gè)子進(jìn)程終止后,輸出以下信息后終止: parent process is killed! # include# include# includeint wait_mark;void waiting(),stop();void main() int p1, p2;signal(sigint,stop);while(p1=fork()=-1);if(p10)/*在父進(jìn)程中*/ while(p2=for
3、k()= =-1); if(p20)/*在父進(jìn)程中*/ wait_mark=1; waiting(0); kill(p1,10); kill(p2,12); wait( ); wait( ); printf(“parent process is killed!n”); exit(0); else/*在子進(jìn)程2中*/ wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf(“child process 2 is killed by parent!n”);lockf(1,0,0);exit(0); else/*在子進(jìn)程1中*/ wait_
4、mark=1; signal(10,stop); waiting(); lockf(1,1,0); printf(“child process 1 is killed by parent!n”); lockf(1,0,0); exit(0);void waiting() while(wait_mark!=0);void stop() wait_mark=0;實(shí)驗(yàn)要求: 運(yùn)行程序并分析結(jié)果。 如果把signal(sigint,stop)放在號(hào)和號(hào)位置,結(jié)果會(huì)怎樣并分析原因。 該程序段前面部分用了兩個(gè)wait(0),為什么? 該程序段中每個(gè)進(jìn)程退出時(shí)都用了語(yǔ)句exit(0),為什么?5.2信號(hào)機(jī)制
5、實(shí)驗(yàn)(二)【實(shí)驗(yàn)?zāi)康摹繉W(xué)習(xí)signal的函數(shù)的使用【實(shí)驗(yàn)原理】利用signal的函數(shù)的機(jī)制來(lái)實(shí)習(xí)我們發(fā)送截獲信號(hào)的功能【實(shí)驗(yàn)內(nèi)容】修改上面的程序,增加語(yǔ)句signal(sigint,sig_ign)和語(yǔ)句signal(sigquit,sig_ign),再觀察程序執(zhí)行時(shí)屏幕上出現(xiàn)的現(xiàn)象,并分析其原因。# include# include# includeint pid1, pid2;int endflag=0;pf1=0;pf2=0;void intdelete() kill(pid1,10); kill(pid2,12);endflag=1;void int1() printf(“child
6、process 1 is killed by parent !n”); exit(0);void int2() printf(“child process 2 is killed by parent !n”); exit(0);main() int exitcode; signal(sigint,sig_ign); signal(sigquit,sig_ign);while(pid1=fork()=-1); if(pid1=0) signal(sigusr1,int1);signal(sigint,sig_ign);pause();exit(0); else while(pid2=fork()
7、= =-1); if(pid2=0) signal(sigusr2,int2);signal(sigint,sig_ign);pause();exit(0); else signal(sigint,intdelete); waitpid(-1,&exitcode,0);/*等待任何子進(jìn)程中斷或結(jié)束*/ printf(“parent process is killed n”); exit(0); 實(shí)驗(yàn)要求:運(yùn)行程序并分析結(jié)果。司機(jī)售票員問(wèn)題(選做題)編程用fork()創(chuàng)建一個(gè)子進(jìn)程代表售票員,司機(jī)在父進(jìn)程中,再用系統(tǒng)調(diào)用signal()讓父進(jìn)程(司機(jī))捕捉來(lái)自子進(jìn)程(售票員)發(fā)出的中斷信號(hào),讓子
8、進(jìn)程(售票員)捕捉來(lái)自(司機(jī))發(fā)出的中斷信號(hào),以實(shí)現(xiàn)進(jìn)程間的同步運(yùn)行。5.3管道通信實(shí)驗(yàn)(一)【實(shí)驗(yàn)?zāi)康摹?、了解什么是管道2、熟悉unix/linux支持的管道通信方式【實(shí)驗(yàn)內(nèi)容】編寫(xiě)程序?qū)崿F(xiàn)進(jìn)程的管道通信。用系統(tǒng)調(diào)用pipe( )建立一管道,二個(gè)子進(jìn)程p1和p2分別向管道各寫(xiě)一句話: child 1 is sending a message! child 2 is sending a message!父進(jìn)程從管道中讀出二個(gè)來(lái)自子進(jìn)程的信息并顯示(要求先接收p1,后p2)。參考程序#include #include #include int pid1,pid2;main( ) int fd2
9、;char outpipe100,inpipe100;pipe(fd); /*創(chuàng)建一個(gè)管道*/while (pid1=fork( )= =-1);if(pid1= =0)lockf(fd1,1,0); sprintf(outpipe,child 1 process is sending message!); /*把串放入數(shù)組outpipe中*/ write(fd1,outpipe,50); /*向管道寫(xiě)長(zhǎng)為50字節(jié)的串*/ sleep(5); /*自我阻塞5秒*/ lockf(fd1,0,0); exit(0);elsewhile(pid2=fork( )= =-1); if(pid2= =0
10、) lockf(fd1,1,0); /*互斥*/ sprintf(outpipe,child 2 process is sending message!); write(fd1,outpipe,50); sleep(5);lockf(fd1,0,0); exit(0); else wait(0); /*同步*/ read(fd0,inpipe,50); /*從管道中讀長(zhǎng)為50字節(jié)的串*/ printf(%s/n,inpipe); wait(0); read(fd0,inpipe,50); printf(%s/n,inpipe); exit(0); 五、運(yùn)行結(jié)果 延遲5秒后顯示child 1 p
11、rocess is sending message! 再延遲5秒child 2 process is sending message!5.4管道通信實(shí)驗(yàn)(二)【實(shí)驗(yàn)?zāi)康摹?、掌握有名管道的創(chuàng)建和讀寫(xiě)方式2、熟悉unix/linux支持的有名管道通信方式【實(shí)驗(yàn)內(nèi)容】1. 創(chuàng)建有名管道2. 本進(jìn)程執(zhí)行循環(huán)等待數(shù)據(jù)被寫(xiě)入到管道中并讀有名管道3. 打開(kāi)有名管道并寫(xiě)數(shù)據(jù)到名管道參考代碼:/read_fifo.c#include #include #include #include #include #include #include #define buffer_size1024int main(int
12、 argc, char *argv) int fd; if (argc 2) fprintf(stdout, usage: %s n, argv0); exit(1); /int open(const char *path, int oflag, .); if (fd = open(argv1, o_rdonly) 0) fprintf(stderr, open fifo %s for reading failed: %sn, argv1, strerror(errno); exit(1); fprintf(stdout, open fifo %s for reading successed.
13、n, argv0); char bufferbuffer_size; ssize_t n; while (1) again: /ssize_t read(int fd, void *buf, size_t count); if (n = read(fd, buffer, buffer_size) 0) if (errno = eintr) goto again; else fprintf(stderr, read failed on %s: %sn, argv1, strerror(errno);exit(1); else if (n = 0) fprintf(stderr, peer clo
14、sed fifo.n); break; else buffern = 0; fprintf(stdout, read %d bytes from fifo: %sn, n, buffer); return 0;/ write_fifo.c#include #include #include #include #include #include #include #include #define buffer_size1024void signal_handler(int s);int main(int argc, char *argv) int fd; if (argc 2) fprintf(
15、stdout, usage: %s n, argv0); exit(1); signal(sigpipe, signal_handler); /int open(const char *path, int oflag, .); if (fd = open(argv1, o_wronly) 0) fprintf(stderr, open fifo %s for writting failed: %sn, argv1, strerror(errno); exit(1); fprintf(stdout, open fifo %s for writting successed.n, argv0); c
16、har bufferbuffer_size; ssize_t n; /char *fgets(char *s, int size, file * stream); while (fgets(buffer, buffer_size, stdin) again: /ssize_t write(int fd, const void *buf, size_t count); if (n = write(fd, buffer, strlen(buffer) 0) if (errno = eintr) goto again; else fprintf(stderr, write() failed on f
17、ifo: %sn, strerror(errno);/ fixme:break; return 0;void signal_handler(int s) fprintf(stdout, caught signal %dn, s);/ create_fifo.c#include #include #include #include #include int main(int argc, char *argv) if (argc 2) fprintf(stdout, usage: %s n, argv0); exit(1); /int mkfifo(const char *path, mode_t
18、 mode); if (mkfifo(argv1, 0644) 0) fprintf(stderr, mkfifo() failed: %sn, strerror(errno); exit(1); return 0;5.5共享內(nèi)存通信實(shí)驗(yàn)【實(shí)驗(yàn)?zāi)康摹?、掌握共享內(nèi)存的創(chuàng)建和讀寫(xiě)方式2、熟悉unix/linux支持的共享內(nèi)存通信方式【實(shí)驗(yàn)內(nèi)容】1. 創(chuàng)建共享內(nèi)存2. 寫(xiě)入到共享內(nèi)存3. 讀數(shù)據(jù)從共享內(nèi)存代碼參考:/write.c#include #include #include #include #include #include #include #include #include #def
19、ine mapped_filename/tmp/test.mmap.1int main(int argc, char *argv) int fd; if (argc 2) fprintf(stdout, usage: %s n, argv0); exit(1); / xxx: step 1, open file, get a fd /int open(const char *pathname, int flags, mode_t mode); if (fd = open(argv1, o_rdwr | o_creat | o_excl, 0644) 0) if (errno = eexist)
20、 fprintf(stderr, fatal error: the target mapped file existed, exit.n); else fprintf(stderr, error: open file failed: (errno = %d)%sn, errno, strerror(errno); exit(1); off_t offset; offset = 1024; / xxx: step 2, create a hole file /off_t lseek(int fildes, off_t offset, int whence); if (lseek(fd, offs
21、et, seek_set) = (off_t) - 1) fprintf(stderr, lseek() failed: %sn, strerror(errno); /fixme: unlink the file close(fd); exit(1); ssize_t n; /ssize_t write(int fd, const void *buf, size_t count); if (n = write(fd, , 1) 0) fprintf(stderr, write() failed: %sn, strerror(errno); exit(1); /* * on success, m
22、map returns a pointer to the mapped area. on error, the value map_failed (that is, (void*) -1) is returned, and errno is set appropriately. on success, munmap returns 0, on failure -1, and errno is set (probably to einval). */* prot_exec pages may be executed. prot_read pages may be read. prot_write
23、 pages may be written. prot_none pages may not be accessed.*/ void *p; / xxx: step 3, mmap(), get a pointer /void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); if (p = mmap(null, 1024, prot_write, map_shared, fd, 0) = map_failed) fprintf(stderr, mmap() failed: %sn,
24、strerror(errno); close(fd); exit(1); close(fd); fprintf(stdout, mapped file to memory, size = %dn, 1024); / xxx: step 4, read/write on shared memory char *banner = hello world.; /void *memcpy(void *dest, const void *src, size_t n); memcpy(p + 256, banner, strlen(banner); / xxx: step 5, munmap(); /in
25、t munmap(void *start, size_t length); pause(); /close(fd); return 0;/ read.c#include #include #include #include #include #include #include #include #include #define mapped_filename/tmp/test.mmap.1#define buffer_size1024int main(int argc, char *argv) int fd; if (argc 2) fprintf(stdout, usage: %s n, a
26、rgv0); exit(1); / xxx: step 1, open file, get a fd /int open(const char *pathname, int flags, mode_t mode); if (fd = open(argv1, o_rdwr) 0) fprintf(stderr, error: open file failed: (errno = %d)%sn, errno, strerror(errno); exit(1); #if 0 off_t offset; offset = 1024; / xxx: step 2, create a hole file
27、/off_t lseek(int fildes, off_t offset, int whence); if (lseek(fd, offset, seek_set) = (off_t) - 1) fprintf(stderr, lseek() failed: %sn, strerror(errno); /fixme: unlink the file close(fd); exit(1); ssize_t n; /ssize_t write(int fd, const void *buf, size_t count); if (n = write(fd, , 1) 0) fprintf(std
28、err, write() failed: %sn, strerror(errno); exit(1); #endif /* * on success, mmap returns a pointer to the mapped area. on error, the value map_failed (that is, (void*) -1) is returned, and errno is set appropriately. on success, munmap returns 0, on failure -1, and errno is set (probably to einval).
29、 */* prot_exec pages may be executed. prot_read pages may be read. prot_write pages may be written. prot_none pages may not be accessed.*/ void *p; / xxx: step 3, mmap(), get a pointer /void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); if (p = mmap(null, 1024, prot
30、_write, map_shared, fd, 0) = map_failed) fprintf(stderr, mmap() failed: %sn, strerror(errno); close(fd); exit(1); close(fd); fprintf(stdout, mapped file to memory, size = %dn, 1024); char bufferbuffer_size; / xxx: step 4, read/write on shared memory /void *memcpy(void *dest, const void *src, size_t
31、n); memcpy(buffer, p+256, 32); fprintf(stdout, %sn, buffer); / xxx: step 5, munmap(); /int munmap(void *start, size_t length); /close(fd); return 0;5.6用消息隊(duì)列編寫(xiě)一個(gè)客戶端服務(wù)器通信的程序【實(shí)驗(yàn)?zāi)康摹客ㄟ^(guò)此實(shí)驗(yàn),學(xué)員可以熟悉消息隊(duì)列的概念,并能夠用消息隊(duì)列編寫(xiě)一個(gè)客戶端服務(wù)器通信的程序?!緦?shí)驗(yàn)原理】本實(shí)驗(yàn)需要用消息隊(duì)列設(shè)計(jì)一個(gè)簡(jiǎn)易的雙人聊天程序(一個(gè)服務(wù)器,兩個(gè)客戶端)。消息隊(duì)列重點(diǎn)在于消息類(lèi)型的匹配,客戶端和服務(wù)端的“通信協(xié)議”的設(shè)計(jì)。設(shè)計(jì)
32、思想如下:服務(wù)器端:接受客戶端發(fā)來(lái)的任何信息,并根據(jù)其消息類(lèi)型,轉(zhuǎn)發(fā)給對(duì)應(yīng)的客戶端。同時(shí),檢測(cè)是否有退出標(biāo)志,有則給所有的客戶端發(fā)送退出標(biāo)志,等待10s后,確定客戶端都退出后,刪除消息隊(duì)列,釋放空間,并退出??蛻舳耍篴和b,a給b發(fā)送信息,先發(fā)給服務(wù)器,由服務(wù)器根據(jù)自定義協(xié)議轉(zhuǎn)發(fā)該消息給b。同時(shí)b接受到消息后,經(jīng)由服務(wù)器給a一個(gè)回執(zhí)信息,以此形成簡(jiǎn)易的聊天模式?!緦?shí)驗(yàn)方法】編寫(xiě)服務(wù)器端程序:#define key_msg 0x101 /使用共有的ipc key#define msgsize 128#include #include #include #include #include main
33、() int msgid; struct msgbuf /定義消息結(jié)構(gòu)體:消息類(lèi)型和消息數(shù)據(jù) long mtype; char mtext128; buf1, buf2; msgid = msgget( key_msg, ipc_creat|0666 ); while( 1 ) /無(wú)限循環(huán),退出標(biāo)志則會(huì)break msgrcv( msgid, &buf1, msgsize, 1l, 0 ); /接受客戶端1的消息printf( receive client1 message: %sn, buf1.mtext ); /打印收到的消息if( buf1.mtext0 = x | buf1.mtext
34、0 = x ) /若是退出標(biāo)志,則給2個(gè)客戶端都發(fā)退出信息 strcpy( buf1.mtext, x ); buf1.mtype = 3l; msgsnd( msgid, &buf1, msgsize, 0 ); buf1.mtype = 4l; msgsnd( msgid, &buf1, msgsize, 0 ); break; buf1.mtype = 4l;msgsnd( msgid, &buf1, msgsize, 0 ); /將客戶端1的消息轉(zhuǎn)發(fā)給客戶端2 msgrcv( msgid, &buf2, msgsize, 2l, 0 ); /接受客戶端2的消息printf( recei
35、ve client2 message: %sn, buf2.mtext ); /打印收到的消息if( buf2.mtext0 = x | buf2.mtext0 = x )/若是退出標(biāo)志,則給2個(gè)客戶端發(fā)退出信息 strcpy( buf2.mtext, x ); buf2.mtype = 3l; msgsnd( msgid, &buf2, msgsize, 0 ); buf2.mtype = 4l; msgsnd( msgid, &buf2, msgsize, 0 ); break; buf2.mtype = 3l;msgsnd( msgid, &buf2, msgsize, 0 ); /將客
36、戶端2的消息轉(zhuǎn)發(fā)給客戶端1 sleep(5); /若退出,則先等待,以確??蛻舳顺绦蛲顺?msgctl( msgid, ipc_rmid, null ); /刪除消息隊(duì)列,釋放空間 exit(0);客戶端1:#define key_msg 0x101#define msgsize 128#include #include #include #include #include main() int msgid; struct msgbuf long mtype; char mtext128; buf1, buf2; msgid = msgget( key_msg, 0666 ); while( 1 ) printf( input the msg to client2: ); gets( buf1.mtext ); buf1.mtype = 1l; msgsnd( msgid, &buf1, msgsize, 0 ); /客戶端1獲取消息并發(fā)往服務(wù)器sleep(1); /等待一秒,以確??蛻舳?已經(jīng)收到并發(fā)了回執(zhí) msgrcv( msgid, &buf2, msgsize, 3l, 0 ); /準(zhǔn)備從客戶端2獲取回執(zhí)消息 if( buf2.mtext0 = x | buf2.mtext0 = x ) printf( client1 will quit!n ); break; p
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 交通運(yùn)輸行業(yè)城市交通管理人才需求與培養(yǎng)策略報(bào)告001
- 人工智能與金融審計(jì)融合報(bào)告:2025年算法在審計(jì)風(fēng)險(xiǎn)識(shí)別中的應(yīng)用研究
- 保健健康技能培訓(xùn)課件
- 維護(hù)心理健康宣講
- 海綿城市調(diào)研報(bào)告
- 企業(yè)責(zé)任火災(zāi)教育
- 俄烏沖突課件
- 非遺中醫(yī)針灸介紹
- 二零二五年度綠色建筑用標(biāo)準(zhǔn)磚采購(gòu)與質(zhì)量控制合同
- 二零二五年度新型工業(yè)園區(qū)廠房土地買(mǎi)賣(mài)合同范本
- 煤化工產(chǎn)業(yè)鏈詳解課件
- RB/T 303-2016養(yǎng)老服務(wù)認(rèn)證技術(shù)導(dǎo)則
- GB/T 6896-2007鈮條
- GB/T 6075.1-2012機(jī)械振動(dòng)在非旋轉(zhuǎn)部件上測(cè)量評(píng)價(jià)機(jī)器的振動(dòng)第1部分:總則
- GB/T 32227-2015船用工作救生衣
- GB 38454-2019墜落防護(hù)水平生命線裝置
- 大學(xué)2023年自主招生報(bào)名登記表
- 小學(xué)體育暑假特色作業(yè)
- 2020四川考研數(shù)學(xué)二真題【含答案】
- 壓縮機(jī)拆除方案
- 部編人教版小學(xué)一年級(jí)上冊(cè)寫(xiě)字表田字格字帖
評(píng)論
0/150
提交評(píng)論