IPC(Inter-Process Communication) - semaphoresemaphore:用來做多個行程的同步處理,例如多個行程存取共一塊shared memory時,可用這加以控制保護。例如行程A用操作號誌為P後,存取共用資源,行程B此時也要操作號誌為P時,會進入等待狀態,當行程A用操作號誌為V後,行程B才可進入存取共用資源。主要是下列三個函式:extern int semctl (int __semid, int __semnum, int __cmd, ...) __THROW;直接控制 semaphore,第二個參數 __semnum為要使用 semaphore 陣列時才要使用,否則為0。第三個參數command指要採取的行動,這裡使用常用的 SETVAL 和 IPC_RMID 來初始化 semaphore和刪除 semaphore。第四個參數是自已宣告的一個union,最少會有下面的成員:union semun{ int val; struct semid_ds *buf; unsigned short *array;};這裡用到設定其成員 val 為 1(V) 來初始化 semaphore。extern int semget (key_t __key, int __nsems, int __semflg) __THROW;新建或取得一個已存在的semaphore,__nsems為取得 semaphore 的數量,幾乎都是1。__semflg的使用方式,類似open函式。extern int semop (int __semid, struct sembuf *__sops, size_t __nsops) __THROW;用來改吳哥窟變 semaphore 的號誌,設定值是傳入第二個參數__sops,其結構為struct sembuf{ unsigned short int sem_num; /* semaphore number */ short int sem_op; /* semaphore operation */ short int sem_flg; /* operation flag */};通常 sem_num為0,sem_op 為號誌的操作值,一般為-1(P)或+1(V),sem_flg一般為 SEM_UNDO,代表如果行程沒有釋放這個semaphore時,允許作業系統幫你釋放。測試:參考前一篇的程式加以修改。加入四個函式,來操作 semaphore:static int set_semvalue(int sem_id) => 初始化 semaphorestatic int del_semvalue(int sem_id) => 刪除 semaphorestatic int semaphore_p(int sem_id) => 設置信號為Pstatic int semaphore_v(int sem_id) => 設置信號為V 1. 主程式建立一塊 shared memory2. 主程式新建並初始化一個 semaphore3. 主程式fork 出一個子程式4. 主程式進入迴圈,做下列動作十次: 設置 semaphore為P後,操作shared memory,印出資料,隨機停1~3秒,設置 semaphore為V5. 子程式和主程式做相同的動作6. 子程式先結束,切斷與 酒店打工shared memory的連結7. 等到子程式已結束,主程式切斷與 shared memory的連結8. 釋放shared memory和 semaphore,結束程式這裡印出來的結果應該是成對的,代表臨界區間被正確的處理。結果應該像下面一樣:1.written by parent1.written by child2.written by parent2.written by child....9.written by parent9.written by child10.written by parent10.written by childchild exit!parent exit!下面為程式:typedef struct sh_mem{ char data[128];}sh_mem_t;#define MAX_LOOP 10const key_t key = 1234;union semun{ int val; struct semid_ds *buf; unsigned short *array;};static int set_semvalue(int sem_id){ union semun sem_union; sem_union.val = 1; return semctl(sem_id, 0, SETVAL, sem_union) != -1;}static int del_semvalue(int sem_id){ union semun sem_union; return semctl(sem_id, 0, IPC_RMID, sem_union) != -1;}static int semaphore_p(int sem_id){ struct sembuf sem_b; 太平洋房屋 sem_b.sem_num = 0; sem_b.sem_op = -1; // P sem_b.sem_flg = SEM_UNDO; return semop(sem_id, &sem_b, 1) != -1;}static int semaphore_v(int sem_id){ struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1; // V sem_b.sem_flg = SEM_UNDO; return semop(sem_id, &sem_b, 1) != -1;}void child_process(int sem_id){ int shmid = shmget(key, sizeof(sh_mem_t), 0666 | IPC_CREAT); if (shmid == -1) { printf("shmget failed\r\n"); exit(EXIT_FAILURE); } // get shared memory void *shared_memory = shmat(shmid, NULL, 0); if (shared_memory == (void*)-1) { printf("shmat failed\r\n"); 辦公室出租 exit(EXIT_FAILURE); } sh_mem_t *p = (sh_mem_t*)shared_memory; int i, pause_time; for (i=0; i { if (!semaphore_p(sem_id)) { printf("child, semaphore_p failed\r\n"); break; } snprintf(p->data, sizeof(p->data), "%d.written by child\n", i+1); printf(p->data); pause_time = rand() % 3; sleep(pause_time); fflush(stdout); if (!semaphore_v(sem_id)) { 信用貸款 printf("child, semaphore_v failed\r\n"); break; } } if (shmdt(shared_memory) == -1) { printf("child, shmdt failed\r\n"); exit(EXIT_FAILURE); }}int main(void){ // create shared memory int shmid = shmget(key, sizeof(sh_mem_t), 0666 | IPC_CREAT); if (shmid == -1) { printf("shmget failed\r\n"); exit(EXIT_FAILURE); } void *shared_memory = shmat(shmid, NULL, 0); if (shared_memory == (void*)-1) { printf("shmat failed\r\n"); 辦公室出租 exit(EXIT_FAILURE); } int sem_id = semget(key, 1, 0666 | IPC_CREAT); if (!set_semvalue(sem_id)) { printf("Failed to initialize semaphore\r\n"); exit(EXIT_FAILURE); } // fork a child process pid_t pid = fork(); if (pid == -1) { perror("fork failed"); exit(1); } if (pid == 0) // child { child_process(sem_id); printf("child exit!\n"); } else // parent { // setting shared memory 小型辦公室 sh_mem_t *p = (sh_mem_t*)shared_memory; bzero(p->data, sizeof(p->data)); int i, pause_time; for (i=0; i<MAX_LOOP; i++) { if (!semaphore_p(sem_id)) { printf("parent, semaphore_p failed\r\n"); break; } snprintf(p->data, sizeof(p->data), "%d.written by parent\n", i+1); printf(p->data); pause_time = rand() % 3; 買屋 sleep(pause_time); fflush(stdout); if (!semaphore_v(sem_id)) { printf("parent, semaphore_v failed\r\n"); break; } } pid_t ret = waitpid(pid, NULL, 0); if (pid != ret) { printf("parent, waitpid failed, %d != %d\r\n", ret, pid); } if (shmdt(shared_memory) == -1) { 買屋網 printf("parent, shmdt failed\r\n"); exit(EXIT_FAILURE); } if (shmctl(shmid, IPC_RMID, 0) == -1) { printf("parent, shmctl failed\r\n"); exit(EXIT_FAILURE); } if (!del_semvalue(sem_id)) { printf("Failed to delete semaphore\r\n"); exit(EXIT_FAILURE); } printf("parent exit!\r\n"); } return EXIT_SUCCESS;}
.msgcontent 小額信貸.wsharing ul li { text-indent: 0; }
分享
Facebook
Plurk
YAHOO!
.msgcontent 小額信貸.wsharing ul li { text-indent: 0; }
分享
Plurk
YAHOO!
全站熱搜
留言列表