訊號量通訊—-摘抄修改網上的例子

來源:互聯網
上載者:User

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/unistd.h>
#include<stdlib.h>
#include<math.h>
#include<errno.h>

/****************************************************
 訊號量的主要作用是限制多線程或者進程對臨界區的訪問,類似於互斥鎖mutex
 使用執行個體:如取票通道只有N個,最多隻能允許N個人同時取票,
 此時若有M個人時,且M>N,需要則訪問不到的通道就可以使用阻塞等待與非阻塞等待
 ******************************************************/

int main() {
    int pid;      //進程ID
    int val = 1;    //為可用資源數量,即通道數N=1
    int semid;  //為號誌(即訊號量)集的識別代號

    key_t semkey;  //唯一索引值

    if ((semkey = ftok("/tmp", 0)) < 0) //將檔案路徑和項目ID(後面那個“1“)轉換為System V IPC Key
            {
        printf("ftok函數轉換出現錯誤。\n");
        exit(1);
    } else
        printf("ftok函數轉換成功,key值為%d\n", semkey);

    if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0700)) < 0) //建立號誌集,其中包含1個號誌
            {
        printf("semget函數建立號誌集出現錯誤。\n");
        exit(2);
    } else
        printf("semget函數建立號誌整合功,號誌集識別代號semid為:%d\n", semid);

    if ((semctl(semid, 0, SETVAL, val)) < 0) //此句與上句合起來的功能是將semid對應的訊號集中的第一個訊號(0表示第一個訊號)的可用資源數量設定為1
            {
        printf("semctl函數設定可用資源數量時出現錯誤。\n");
        exit(9);
    } else
        printf("semctl函數設定可用資源數量成功。\n");

    if ((pid = fork()) < 0) {
        printf("fork函數建立子進程出現錯誤。\n");
        exit(3);
    } else if (pid > 0) //父進程,先索取共用資源,而後釋放
            {
        struct sembuf p_op_buf, v_op_buf;
        printf("父進程ID為:%d,該進程將要索取共用資源\n", getpid());
        p_op_buf.sem_num = 0;
        p_op_buf.sem_op = -1;  //申請資源是-1,讓出資源是+1
        if (semop(semid, &p_op_buf, 1) < 0) //以上三行向semid代表的號誌集的第一個號誌申請一個資源
                {
            printf("父進程中,semop函數索取共用資源出現錯誤。\n");
            exit(4);
        } else {
            int i;
            printf("父進程中,semop函數索取共用資源成功,索取個數為:%d\n", abs(p_op_buf.sem_op));
            printf("ID為%d的父進程現在要睡上6秒鐘。\n", getpid());
            for (i = 6; i > 0; i--) {
                printf("%d號進程(父進程)還要睡%d秒鐘……\n", getpid(), i);
                sleep(1);
            }
            printf("%d號進程(父進程)已經醒來,並將釋放資源。\n", getpid());
            v_op_buf.sem_num = 0;
            v_op_buf.sem_op = 1;
            p_op_buf.sem_flg = 0; //該標誌位此處不清零不會出現錯誤,但下面子進程中的該標誌位應清零,因為那時父進程已經佔據了資源,子進程申請不到資源的情況下,該標誌位如果不清零(比如採用不賦值的預設處理),可能會出現錯誤。
            if (semop(semid, &v_op_buf, 1) < 0) //以上三行將釋放一個資源給semid代表的號誌集第一個號誌
                    {
                printf("父進程中,semop函數索取共用資源出現錯誤。\n");
                exit(5);
            } else {
                printf("ID號為%d的父進程中,semop函數釋放共用資源成功,釋放個數為:%d\n", getpid(),
                        v_op_buf.sem_op);
                sleep(1);
            }
        }
    } else //子進程不斷申請共用資源,申請到後聲明一下,然後釋放
    {
        struct sembuf p_op_buf, v_op_buf;
        sleep(2); //等待父進程將唯一的資源佔用
        printf("子進程ID為:%d,該進程將要索取共用資源\n", getpid());
        p_op_buf.sem_num = 0;
        p_op_buf.sem_op = -1;

        //sem_flg:訊號操作標誌,可能的選擇有兩種
        //IPC_NOWAIT 對訊號的操作不能滿足時,semop()不會阻塞,並立即返回,同時設定錯誤資訊。
        //SEM_UNDO 程式結束時(不論正常或不正常),保證訊號值會被重設為semop()調用前的值。這樣做的目的在於避免程式在異常情況下結束時未將鎖定資源解鎖,造成該資源永遠鎖定。
        p_op_buf.sem_flg = SEM_UNDO; //該標誌位不用要清零,此處不清零將出現錯誤,0表示預設阻塞

        //阻塞申請
        if (semop(semid, &p_op_buf, 1) < 0) //向semid代表的號誌集的第一個號誌申請一個資源,申請不到就一直在這兒等著,什麼時候有了資源,什麼時候接著向下進行
                {
            printf("子進程中,semop函數索取共用資源出現錯誤:%d\n", errno);
            exit(6);
        } else
            printf("**********子程式已經成功申請到資源!**********\n");
        v_op_buf.sem_num = 0;
        v_op_buf.sem_op = 1;
        if (semop(semid, &v_op_buf, 1) < 0) //以上三行將釋放一個資源給semid代表的號誌集第一個號誌
                {
            printf("子進程中,semop函數索取共用資源出現錯誤。\n");
            exit(7);
        } else {
            printf("子進程中,semop函數釋放共用資源成功,釋放個數為:%d\n", v_op_buf.sem_op);
            printf("ID號為%d的進程(子進程)退出!\n", getpid());

            if (semctl(semid, 0, IPC_RMID, 0) < 0) {
                printf("調用semctl刪除訊號量集出現錯誤。\n");
                exit(8);
            } else {
                printf("識別代號為%d的訊號量集已經被刪除\n", semid);
                exit(0);
            }
        }
    }
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.