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!

arrow
arrow
    全站熱搜

    ka40kawnje 發表在 痞客邦 留言(0) 人氣()