更多技術文章地址:http://www.hqyj.com/news/emb211.htm?lcg-ee 1.實驗目的 通過編寫共享內存實驗,進一步了解使用共享內存的具體步驟,同時加深對共享內存的理解。在本實驗中,采用信號量作為同步機制完善兩個進程(“生產者”和“消費者”)之間的通信,其功能類似于4.6節中的實例。在實例中使用信號量同步機制。 2.實驗內容 該實現要求利用共享內存實現文件的打開和讀寫操作。 3.實驗步驟 (1)畫出流程圖。該實驗流程圖如圖1所示。 圖1 實驗流程圖 (2)編寫代碼。下面是共享內存緩沖區的數據結構的定義: /* shm_com.h */ #include #include #include #include #include #include #include #define SHM_BUFF_SZ 2048 struct shm_buff { int pid; char buffer[SHM_BUFF_SZ]; }; 以下是“生產者”程序部分: /* sem_com.h 和 sem_com.c 與4.4節示例中的同名程序相同 */ /* producer.c */ #include "shm_com.h" #include "sem_com.h" #include int ignore_signal(void) { /* 忽略一些信號,以免非法退出程序 */ signal(SIGINT, SIG_IGN); signal(SIGSTOP, SIG_IGN); signal(SIGQUIT, SIG_IGN); return 0; } int main() { void *shared_memory = NULL; struct shm_buff *shm_buff_inst; char buffer[BUFSIZ]; int shmid, semid; /* 定義信號量,用于實現訪問共享內存的進程間的互斥 */ ignore_signal(); /* 防止程序非正常退出 */ semid = semget(ftok(".", 'a'), 1, 0666|IPC_CREAT); /* 創建一個信號量 */ init_sem(semid);/* 初始值為1 */ /* 創建共享內存 */ shmid = shmget(ftok(".", 'b'), sizeof(struct shm_buff), 0666|IPC_CREAT); if (shmid == -1) { perror("shmget failed"); del_sem(semid); exit(1); } /* 將共享內存地址映射到當前進程地址空間 */ shared_memory = shmat(shmid, (void*)0, 0); if (shared_memory == (void*)-1) { perror("shmat"); del_sem(semid); exit(1); } printf("Memory attached at %X\n", (int)shared_memory); /* 獲得共享內存的映射地址 */ shm_buff_inst = (struct shared_use_st *)shared_memory; do { sem_p(semid); printf("Enter some text to the shared memory(enter 'quit' to exit):"); /* 向共享內存寫入數據 */ if (fgets(shm_buff_inst->buffer, SHM_BUFF_SZ, stdin) == NULL) { perror("fgets"); sem_v(semid); break; } shm_buff_inst->pid = getpid(); sem_v(semid); } while(strncmp(shm_buff_inst->buffer, "quit", 4) != 0); /* 刪除信號量 */ del_sem(semid); /* 刪除共享內存到當前進程地址空間中的映射 */ if (shmdt(shared_memory) == 1) { perror("shmdt"); exit(1); } exit(0); } 以下是“消費者”程序部分: /* customer.c */ #include "shm_com.h" #include "sem_com.h" int main() { void *shared_memory = NULL; struct shm_buff *shm_buff_inst; int shmid, semid; /* 獲得信號量 */ semid = semget(ftok(".", 'a'), 1, 0666); if (semid == -1) { perror("Producer is'nt exist"); exit(1); } /* 獲得共享內存 */ shmid = shmget(ftok(".", 'b'), sizeof(struct shm_buff), 0666|IPC_CREAT); if (shmid == -1) { perror("shmget"); exit(1); } /* 將共享內存地址映射到當前進程地址空間 */ shared_memory = shmat(shmid, (void*)0, 0); if (shared_memory == (void*)-1) { perror("shmat"); exit(1); } printf("Memory attached at %X\n", (int)shared_memory); /* 獲得共享內存的映射地址 */ shm_buff_inst = (struct shm_buff *)shared_memory; do { sem_p(semid); printf("Shared memory was written by process %d :%s", shm_buff_inst->pid, shm_buff_inst->buffer); if (strncmp(shm_buff_inst->buffer, "quit", 4) == 0) { break; } shm_buff_inst->pid = 0; memset(shm_buff_inst->buffer, 0, SHM_BUFF_SZ); sem_v(semid); } while(1); /* 刪除共享內存到當前進程地址空間中的映射 */ if (shmdt(shared_memory) == -1) { perror("shmdt"); exit(1); } /* 刪除共享內存 */ if (shmctl(shmid, IPC_RMID, NULL) == -1) { perror("shmctl(IPC_RMID)"); exit(1); } exit(0); } 4.實驗結果 實驗運行結果如下: $./producer Memory attached at B7F90000 Enter some text to the shared memory(enter 'quit' to exit):First message Enter some text to the shared memory(enter 'quit' to exit):Second message Enter some text to the shared memory(enter 'quit' to exit):quit $./customer Memory attached at B7FAF000 Shared memory was written by process 3815 :First message Shared memory was written by process 3815 :Second message Shared memory was written by process 3815 :quit |