/* * 進程間通信之信號量,代碼源自《Linux程序設計》 */ #include <iostream> #include <string> #include <unistd.h> #include <stdlib.h> #include <stdio.h> // 使用信號量必須包含該文件 #include <sys/sem.h> using namespace std; // 自定義的一個聯合體,信號量相關函數需要使用 union semun { int val; struct semid_ds* buf; unsigned short* array; }; // 初始化信號量 int set_semvalue(int semid) { union semun sem_union; // 信號量的初始值是1 sem_union.val = 1; // 使用semctl函數去設置它,參數為SETVAL if(semctl(semid,0,SETVAL,sem_union) == -1) { cout << "set_semvalue failed!"<< endl; return 0; } return 1; } // 刪除一個信號量 int del_semvalue(int semid) { union semun sem_union; // 使用semctl去刪除它,標志是IPC_RMID if(semctl(semid,0,IPC_RMID,sem_union) == -1) { cout << "del_semvalue failed!"<< endl; return 0; } return 1; } // 等待信號量 int semaphore_p(int semid) { struct sembuf sem_b; sem_b.sem_num = 0; // 如果不是使用一組信號,那麼這個值一般都是0 sem_b.sem_op = -1; // 表示進行P操作 sem_b.sem_flg = SEM_UNDO; // 默認都要設置為SEM_UNDO(這是為了,當進程異常退出的時候,系統可以釋放進程持有的信號量) // 調用semop進行P操作 if(semop(semid,&sem_b,1) == -1) { cout << "semaphore_p failed!"<< endl; return 0; } return 1; } // V操作,釋放信號量 int semaphore_v(int semid) { struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1; // 1表示進行V操作 sem_b.sem_flg = SEM_UNDO; if(semop(semid,&sem_b,1) == -1) { cout << "semaphore_v failed!"<< endl; return 0; } return 1; } int main(int argc,char* argv[]) { // 信號量的id int sem_id; char op_char = 'O'; // 創建或者打開一個信號量(信號量不存在就創建、存在就打開) sem_id = semget((key_t)1234,1,0666|IPC_CREAT); // 用一個額外的參數去控制哪個進程對信號量進行初始化,即如果當前進程有額外的參數 // 那麼它就對信號量進行初始化 if(argc > 1) { // 初始化信號量 if(set_semvalue(sem_id) == 0) { return -1; } op_char = 'X'; sleep(2); } for(int i = 0; i < 10; ++i) { // 等待信號量 if(semaphore_p(sem_id) == 0) { return -1; } // 打印一些信息 cout << op_char ; cout.flush(); sleep(2); cout << op_char; cout.flush(); // 釋放信號量,即V操作 if(semaphore_v(sem_id) == 0) { return -1; } sleep(2); } // 執行結束,打印一些信息 cout << endl << getpid() << " - finished" << endl; // 用額外的參數去控制進程去刪除信號量 if(argc > 1) { if(del_semvalue(sem_id) == 0) { return -1; } } return 0; }