共享內(nèi)存和信號(hào)量進(jìn)程間通信_(tái)第1頁(yè)
共享內(nèi)存和信號(hào)量進(jìn)程間通信_(tái)第2頁(yè)
共享內(nèi)存和信號(hào)量進(jìn)程間通信_(tái)第3頁(yè)
共享內(nèi)存和信號(hào)量進(jìn)程間通信_(tái)第4頁(yè)
共享內(nèi)存和信號(hào)量進(jìn)程間通信_(tái)第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、實(shí)驗(yàn)7 共享內(nèi)存和信號(hào)量(進(jìn)程間通信)邢衛(wèi) 2008-11-26修訂實(shí)驗(yàn)?zāi)康膶W(xué)習(xí)并掌握Linux系統(tǒng)中的進(jìn)程間通信機(jī)制,包括共享內(nèi)存和信號(hào)量。實(shí)驗(yàn)內(nèi)容1. 學(xué)習(xí)共享內(nèi)存相關(guān)的系統(tǒng)調(diào)用shmget(), shmat(), shmdt, shmctl()2. 學(xué)習(xí)信號(hào)量(semaphore)相關(guān)的系統(tǒng)調(diào)用semget(), semop(), semctl()3. 學(xué)習(xí)信號(hào)(signal)相關(guān)的系統(tǒng)調(diào)用signal(), atexit()等4. 完成邊干邊學(xué)第6.4.1節(jié)的實(shí)驗(yàn)程序的編輯、編譯、運(yùn)行操作5. 分析、學(xué)習(xí)實(shí)驗(yàn)程序的工作過程和原理6. 選做:學(xué)習(xí)邊干邊學(xué)第6章,結(jié)合使用聯(lián)機(jī)手冊(cè)(可以從m

2、an 2 ipc命令開始),編程練習(xí)各種進(jìn)程間通信機(jī)制實(shí)驗(yàn)步驟1以stu帳號(hào)登錄2編輯reader_writer1.c程序注意:在193頁(yè)delete()函數(shù)中,注意改成if (mysemctl(Semid, 0, IPC_RMID, (union semun)0) = -1) 限于實(shí)驗(yàn)的時(shí)間,該文件已預(yù)先存放在/home/stu/.kernel/lab6目錄下,可以直接使用。但每位同學(xué)務(wù)必通讀并理解該程序。登錄后,使用 cd .kernel/lab6 命令進(jìn)入該文件所在目錄,繼續(xù)以下實(shí)驗(yàn)步驟。3編譯 gcc reader_writer1.c -o reader_writer14運(yùn)行 ./re

3、ader_writer1注意記錄下共享內(nèi)存的id號(hào)5使用 Alt+F2切換到第2個(gè)登錄窗口,再次以stu帳號(hào)登錄可以使用who命令查看驗(yàn)證此時(shí)有兩個(gè)stu用戶已登錄可以使用ps l命令查看這兩個(gè)stu用戶的進(jìn)程6在第2個(gè)stu用戶窗口中,輸入 ./reader_writer1 共享內(nèi)存的id號(hào)注意:此時(shí),第2個(gè)stu用戶窗口中的進(jìn)程擔(dān)當(dāng)writer角色,第1個(gè)stu用戶窗口中的進(jìn)程擔(dān)當(dāng)reader角色。7在第2個(gè)窗口中,多次輸入信息;使用Alt+F1和Alt+F2在兩個(gè)窗口間切換,觀察你對(duì)writer的輸入,writer已經(jīng)通過共享內(nèi)存?zhèn)鬟f給了reader。8此時(shí),你還可以使用Alt+F3切換

4、到第3個(gè)登錄窗口,并以stu帳號(hào)登錄可以使用who命令驗(yàn)證有3個(gè)stu用戶登錄;可以經(jīng)常性使用ps l命令來查看另外兩個(gè)窗口中的進(jìn)程的狀態(tài)9切換到writer窗口(第2個(gè)窗口),通過對(duì)writer的問題回答“2”,退出writer。切換到reader窗口(第1個(gè)窗口),通過Ctrl+C終止reader進(jìn)程。思考題1. 同樣的源程序,reader和writer進(jìn)程是怎樣各自找到自己的定位的?2. reader和writer是怎樣通過信號(hào)量(semphore)實(shí)現(xiàn)同步的?writer是如何得知這一對(duì)信號(hào)量的id的?3. 數(shù)據(jù)是如何從writer傳遞到reader的?4. writer是如何得知共享

5、內(nèi)存的id的?5. 在reader中,是如何捕獲Ctrl-C信號(hào)(signal)的?捕獲后是如何處理的?6. 一般來說,在Linux中使用共享內(nèi)存(shared memory)的流程應(yīng)該怎樣?使用哪些系統(tǒng)調(diào)用?7. 一般來說,在Linux中使用信號(hào)量(semaphore)的流程應(yīng)該怎樣?使用哪些系統(tǒng)調(diào)用?8. 這里的共享內(nèi)存,和使用帶CLONE_VM標(biāo)志的clone()系統(tǒng)調(diào)用創(chuàng)建的兩個(gè)task之間共享的內(nèi)存,有什么異同?參考資料l 邊干邊學(xué)(第1版)第6章,“共享內(nèi)存”n 具體源程序和實(shí)驗(yàn)操作詳見6.4.1節(jié)附錄1共享內(nèi)存的使用共享內(nèi)存共有4個(gè)系統(tǒng)調(diào)用:shmget,shmat,shmdt,

6、shmctlint shmget(key_t key, int size, int shmflg);典型的創(chuàng)建共享內(nèi)存的用法l shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | mode);l shmid = shmget(IPC_PRIVATE, size, mode);void *shmat(int shmid, const void *shmaddr, int shmflg);典型用法:l shmaddr = shmat(shmid, NULL, 0);int shmdt(const void *shmaddr);int shmctl(in

7、t shmid, int cmd, struct shmid_ds *buf);典型用法:l 取狀態(tài)shmctl(shmid, IPC_STAT, &buf);l 刪除shmctl(shmid, IPC_RMID, NULL);實(shí)例struct shmid_ds buf;shmid = shmget(key, size, flag);if (shmid = -1) / error handling .shmctl(shmid, IPC_STAT, &buf);/ 分析利用buf中的信息shmaddr = (char *)shmat(id, NULL, 0);if (shmadd

8、r = -1) / error handling .通過shmaddr使用共享內(nèi)存的部分,如strcpy, sprintf, memcmp, 賦值操作,等等shmdt(shmaddr);shmctl(shmid, IPC_RMID, NULL);附錄2 實(shí)驗(yàn)原理說明本實(shí)驗(yàn)將建立一個(gè)利用共享內(nèi)存來傳遞信息的程序,一個(gè)writer,一個(gè)reader,writer從用戶處獲得輸入,然后將其寫入共享內(nèi)存,reader 從共享內(nèi)存獲取信息,然后再在屏幕上打印出來。利用共享內(nèi)存在進(jìn)程之間傳遞信息時(shí),需要一種同步機(jī)制,必須有一種途徑讓reader知道什么時(shí)候writer已經(jīng)把信息放入了共享內(nèi)存。最簡(jiǎn)單的方法

9、,是在某處設(shè)置一個(gè)字節(jié),當(dāng)writer的數(shù)據(jù)寫入完畢后,即把該字節(jié)設(shè)置為1。但是這也意味著reader 必須不停地測(cè)試這個(gè)字節(jié),直到該字節(jié)改變?yōu)橹梗@是非常浪費(fèi)的。同樣,對(duì)于writer 來說,也必須有一種途徑知道什么時(shí)候reader 已經(jīng)取走了共享內(nèi)存的數(shù)據(jù),從而可以向共享內(nèi)存寫入新的數(shù)據(jù)。因此,我們考慮用信號(hào)量(semaphore)來解決這個(gè)程序?qū)τ诠蚕韮?nèi)存進(jìn)行操作的同步問題,關(guān)于信號(hào)量的編程,請(qǐng)參考Linux man手冊(cè)。目前這個(gè)程序只支持兩個(gè)進(jìn)程,一個(gè)reader,一個(gè)writer。在稍后的時(shí)候,我們將改進(jìn)這個(gè)程序使得其能夠支持任意數(shù)目的進(jìn)程。在這個(gè)程序中,我們使用兩個(gè)信號(hào)量,一個(gè)用于

10、讀(SN_READ),一個(gè)用于寫(SN_WRITE)。SN_READ初始化為1,SN_WRITE初始化為0。即SN_READ這個(gè)信號(hào)量在最初的時(shí)候就是被鎖住的,而SN_WRITE這個(gè)信號(hào)量則不是。writer在往共享內(nèi)存里寫信息時(shí),首先要鎖定SN_WRITE信號(hào)量。在寫完之后,釋放SN_READ信號(hào)量,使得reader可以讀取該信息;鎖定SN_WRITE這個(gè)信號(hào)量,是為了防止writer 多次打印共享內(nèi)存中的信息。reader讀取共享內(nèi)存的信息時(shí),相應(yīng)地要先鎖定SN_READ這個(gè)信號(hào)量,讀取信息后,釋放SN_WRITE這個(gè)信號(hào)量,使得writer又可以往共享內(nèi)存里面寫入信息。程序源代碼參見re

11、ader_writer1.c。編譯:gcc reader_writer1.c o reader_writer1在此之后,即可啟動(dòng)reader。實(shí)驗(yàn)中必須先啟動(dòng)reader,因?yàn)槭褂玫男盘?hào)量、共享內(nèi)存都是在reader中申請(qǐng)的。在命令行輸入:./reader_writer1運(yùn)行結(jié)果為:reader begin to run,and the id of share memory is 229376 wait for the writers output information.然后再啟動(dòng)writer,帶的參數(shù)為reader 申請(qǐng)的共享內(nèi)存的標(biāo)識(shí)符。在命令行輸入:./reader_writer1 2

12、29376運(yùn)行結(jié)果為:writer begin to run,the id of share memory is 229376, semaphore id is 196608menu1.send a message2.quitinput your choice(1-2):1wait for reader to read in information.finishplease input information:在提示后面輸入:hello, reader隨即,reader 那邊將打印這條信息。然后循環(huán)往復(fù)。不再累贅。關(guān)于退出:writer 可以通過菜單退出,reader 可以在writer 退出

13、后,按Ctrl+C退出,退出reader時(shí),它將自動(dòng)刪除最初申請(qǐng)信號(hào)量。附錄3 reader_write1.c源程序/* reader_writer1.c communicate through shared memory */#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <stdlib.h>#include <errno.h>#includ

14、e <string.h>#include <signal.h>/* The union for semctl may or may not be defined for us.This code,defined in linux's semctl() manpage,is the proper way to attain it if necessary */#if defined (_GNU_LIBRARY_)&& !defined (_SEM_SEMUN_UNDEFINED)/* union semun is defined by includ

15、ing <sys/sem.h> */#else/* according to X/OPEN we have to define it ourselves */union semunint val;/* value for SETVAL */struct semid_ds *buf;/* buffer for IPC_STAT,IPC_SET */unsigned short int *array;/* array for GETALL,SETALL */struct seminfo *_buf;/* buffer for IPC_INFO */;#endif#define SHMD

16、ATASIZE 1000#define BUFFERSIZE (SHMDATASIZE - sizeof(int)#define SN_READ 0#define SN_WRITE1int Semid = 0;void reader(void);void writer(int shmid);void delete(void);void sigdelete(int signum);void locksem(int semid,int semnum);void unlocksem(int semid,int semnum);void waitzero(int semid,int semnum);v

17、oid write(int shmid,int semid,char *buffer);int mysemget(key_t key,int nsems,int semflg);int mysemctl(int semid,int semnum,int cmd,union semun arg);int mysemop(int semid,struct sembuf *sops,unsigned nsops);int myshmget(key_t key,int size,int shmflg);void *myshmat(int shmid,const void *shmaddr,int sh

18、mflg);int myshmctl(int shmid,int cmd,struct shmid_ds *buf);int main(int argc,char *argv)/* no command line parameter, a reader */if(argc < 2)reader();elsewriter(atoi(argv1);return 0;void reader(void)union semun sunion;int semid,shmid;void *shmdata;char *buffer;/* first, create a semaphore */semid

19、 = mysemget(IPC_PRIVATE,2,SHM_R|SHM_W);Semid = semid;/* at exit, delete the semaphore */atexit(&delete);signal(SIGINT,&sigdelete);/* */sunion.val = 1;mysemctl(semid,SN_READ,SETVAL,sunion);sunion.val = 0;mysemctl(semid,SN_WRITE,SETVAL,sunion);/* create a shared memory */shmid = myshmget(IPC_P

20、RIVATE,SHMDATASIZE,IPC_CREAT|SHM_R|SHM_W);/* map the shared memory into the process' virtual memory */shmdata = shmat(shmid,0,0);/* mark the shared memory as "destroyed", and leave it to be destroyed automatically */shmctl(shmid,IPC_RMID,NULL);/* */*(int *)shmdata = semid;buffer = shmd

21、ata + sizeof(int);printf("n reader begin to run,and the id of share memory is %d * n",shmid);/*reader's main loop*/while(1)printf(" n wait for the writer's output information .");fflush(stdout);locksem(semid,SN_WRITE);printf(" finish n");printf(" received i

22、nformation: %s n",buffer);unlocksem(semid,SN_READ);void writer(int shmid)int semid;void *shmdata;char *buffer;/* map the shared memory into process' virtual memory */shmdata = myshmat(shmid,0,0);semid = *(int *)shmdata;buffer = shmdata + sizeof(int);printf(" n writer begin to run,the i

23、d of share memory is %d, the semaphore is %d n",shmid,semid);/*writer's main loop*/while(1)char input3;printf("n menu n 1.send a message n");printf(" 2.quit n");printf("input your choice(1-2):");fgets(input,sizeof(input),stdin);switch(input0)case '1':wr

24、ite(shmid,semid,buffer);break;case '2':exit(0);break;void delete(void)printf("n quit; delete the semaphore %d n",Semid);/* delete the semaphore */if(mysemctl(Semid,0,IPC_RMID,(union semun)0) = -1)printf("Error releasing semaphore.n");void sigdelete(int signum)/* Calling e

25、xit will conveniently trigger the normal delete item. */exit(0);void locksem(int semid,int semnum)struct sembuf sb;sb.sem_num = semnum;sb.sem_op = -1;sb.sem_flg = SEM_UNDO;mysemop(semid,&sb,1);void unlocksem(int semid,int semnum)struct sembuf sb;sb.sem_num = semnum;sb.sem_op = 1;sb.sem_flg = SEM

26、_UNDO;mysemop(semid,&sb,1);void waitzero(int semid,int semnum)struct sembuf sb;sb.sem_num = semnum;sb.sem_op = 0;sb.sem_flg = 0;/* No modification so no need to undo */mysemop(semid,&sb,1);void write(int shmid,int semid,char *buffer)printf("n wait for reader to read in information .&quo

27、t;);fflush(stdout);locksem(semid,SN_READ);printf("finish n");printf("please input information: ");fgets(buffer,BUFFERSIZE,stdin);unlocksem(semid,SN_WRITE);int mysemget(key_t key,int nsems,int semflg)int retval;retval = semget(key,nsems,semflg);if(retval = -1)printf("semget key %d,nsems %d failed: %s ",key,nsems,strerror(errno);exit(255);return retval;int mysemctl(int semid,int semnum,int cmd,union semun arg)int retval;retval = semctl(semid,semnum,cmd,arg);if(retval = -1)printf("semctl semid %d,semnum %d,cmd %d failed: %s

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論