一、 實驗目的
熟悉并掌握管道機制,并實現進程間通信 熟悉并掌握共享內存機制,并實現進程間通信
二、 實驗內容
任務一:
(1)閱讀以上父子進程利用管道進行通信的例子(例1),寫出程序的運行結果并分析。 (2)編寫程序:父進程利用管道將一字符串交給子進程處理。子進程讀字符串,將里面的字符反向后再交給父進程,父進程最后讀取并打印反向的字符串。
任務二、
(1)閱讀例2的程序,運行一次該程序,然后用ipcs命令查看系統中共享存儲區的情況,再次執行該程序,再用ipcs命令查看系統中共享內存的情況,對兩次的結果進行比較,并分析原因。最后用ipcrm命令刪除自己建立的共享存儲區。 (有關ipcs和ipcrm介紹見后面一頁) (2)每個同學登陸兩個窗口,先在一個窗口中運行例3程序1(或者只登陸一個窗口,先在該窗口中以后臺方式運行程序1),然后在另一個窗口中運行例3程序2,觀察程序的運行結果并分析。運行結束后可以用ctrl+c結束程序1的運行。 (3)編寫程序:使用系統調用shmget(),shmat(),shmdt(),shmctl(),編制程序。要求在父進程中生成一個30字節長的私有共享內存段。接下來,設置一個指向共享內存段的字符指針,將一串大寫字母寫入到該指針指向的存貯區。調用fork()生成子進程,讓子進程顯示共享內存段中的內容。接著,將大寫字母改成小寫,子進程修改共享內存中的內容。之后,子進程將脫接共享內存段并退出。父進程在睡眠5秒后,在此顯示共享內存段中的內容(此時已經是小寫字母)。
三、 代碼及運行結果分析 任務一:
(1)#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <string.h>
int main()
{ int x,fd[2];char buf[30],s[30];pipe(fd);while ((x=fork())==-1);if (x==0){close(fd[0]);printf("Child Process!\n");strcpy(buf,"This is an example\n");write(fd[1],buf,30);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],s,30);printf("%s\n",s);}
}
調用pipe創建一個管道,接著調用fork產生兩個進程,首先執行子進程,關閉管道出口,通過管道入口向管道中寫入內容。接著在父進程中關閉管道入口,通過管道出口從管道中讀取寫入內容,輸出。
(2)#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(){int x,count,left,right,temp,fd[2],fe[2];char c,buf[30],s[30];pipe(fd);pipe(fe);printf("please input a line of char:\n");scanf("%s",buf);while((x=fork())==-1);if(x==0){close(fd[0]);close(fe[1]);printf("Child Process!\n");write(fd[1],buf,30);read(fe[0],buf,30);printf("%s\n",buf);exit(0);}else{close(fd[1]);close(fe[0]);count=0;do{read(fd[0],&c,1);s[count++]=c;}while(c!='\0');printf("Parent Process!\n");printf("%s\n",s);count-=2;for(left=0,right=count;left<=count/2;left++,right--){temp=s[left];s[left]=s[right];s[right]=temp;}write(fe[1],s,30);wait(0);}
}
任務二:
(1)#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main()
{
key_t key=231;
int shmid_1,shmid_2;
if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){perror("shmget shmid_1");exit(1);
}
printf("First shared memory identifier is %d\n",shmid_1);
if ((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){perror("shmget shmid_2");exit(2);
}
printf("Second shared memory identifier is %d\n",shmid_2);
exit(0);
return 0;
}
成功返回共享內存段標識符。對存在于內核存儲空間中的每個共享內存段,內核均有shmid_ds。失敗,返回-1。 參數key用來創建IPC標識符。參數size決定內存段的大小.參數shmflag,用于設置訪問權限及標識創建條件。? 對比:第二次的共享內存段中的關鍵字,共享內存標識符,訪問權限,字節等都是不一樣的。
(2)
程序一:#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 131 /*在實際實驗過程中,為了避免每個同學建立的共享存儲區關鍵字一樣而相互干擾,關鍵字請用學號末3位*/
#define K 1024int shmid;
void cleanup()
{
shmctl(shmid,IPC_RMID,0);
exit(0);
}
int main (){
int i,*pint;
char *addr;
//extern int shmat();
// extern cleanup();
for(i=0;i<20;i++) signal(i,cleanup);
shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享區SHMKEY */
addr=shmat(shmid,0,0);/*掛接,并得到共享區首地址 */
printf ("addr 0x%x\n",addr);
pint=(int *)addr;
for (i=0;i<256;i++) *pint++=i;
pause();/*等待接收進程讀 */
}
程序二:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMKEY 131 /*在實際實驗過程中,為了避免每個同學建立的共享存儲區關鍵字一樣而相互干擾,關鍵字請用學號末3位*/
#define K 1024
int shmid;
main (){
int i,*pint;
char *addr;
//extern char * shmat ();
shmid=shmget(SHMKEY,8*K,0777);/*取共享區SHMKEY的id */
addr=shmat(shmid,0,0);/*連接共享區*/
pint=(int *)addr;
for (i=0;i<256;i++)
printf("%d\n",*pint++);/*打印共享區中的內容*/
}
首先系統調用shmctl對shmid指向內存段進行刪除,接著系統調用shmget創建共享內存段,返回標識符給shmid,系統再次調用shmat連接內存段,返回地址addr。程序1運行時,該程序開始執行,系統調用shmget創建共享內存段,再通過調用shmat掛接內存段,最終輸出轉換后的前255。
(3)#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 131
#define K 1024
int shmid_1,shmid_2;
int main ()
{int x,y,i,*pint;char *addr_1,*addr_2;char words[30]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D'};shmid_1=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享區SHMKEY */addr_1=shmat(shmid_1,0,0);/*掛接,并得到共享區首地址*/pint=(int *)addr_1;printf ("addr_1 0x%x\n",addr_1);for (i=0;i<26;i++) {*pint=words[i];pint++;}while((x=fork())==-1);if(x==0){shmid_2=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享區SHMKEY */addr_2=shmat(shmid_2,0,0);/*掛接,并得到共享區首地址*/pint=(int *)addr_2;for(i=0;i<26;i++){printf("%c ",*pint);*pint=*pint+32;pint++;if(i==25)printf("\n");}y=shmdt(addr_2);exit(0);}else{sleep(5);pint=(int *)addr_1;for(i=0;i<26;i++){printf("%c ",*pint);pint++;if(i==25)printf("\n");}}
}
四、 實驗心得 通過本次實驗簡單了解了管道進程間通信形式,初步掌握利用管道進行進程通信的程序設計,基本完成了本次實驗的要求。學會了shmget()、shmat()、shmdt()、shmctl()4個調用,ipcs、ipcrm命令使用:還加深了對操作系統中各進程之間的通信協同的了解。
總結
以上是生活随笔 為你收集整理的操作系统——实验贰——进程通信(一)管道及共享内存 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。