|簡體中文

比思論壇

 找回密碼
 按這成為會員
搜索



查看: 432|回復: 0
打印 上一主題 下一主題

linux信号量(进程间通信)

[複製鏈接]

989

主題

1

好友

5288

積分

教授

Rank: 8Rank: 8

  • TA的每日心情

    2024-9-18 07:17
  • 簽到天數: 1252 天

    [LV.10]以壇為家III

    推廣值
    2
    貢獻值
    378
    金錢
    1714
    威望
    5288
    主題
    989

    回文勇士 文明人 中學生 高中生 簽到勳章 簽到達人 男生勳章 大學生 文章勇士 附件高人 附件達人 文章達人 教授

    樓主
    發表於 2012-9-14 19:02:37
    将使用一个程序来演示信号量的使用,程序用PV操作控制信号量,以操作临界区,P操作让信号量减1,V操作让信号量加1,而PV操作之间的代码即为临界区关键代码。每次只能由一个进程访问。



    程序创建出一个子进程,在两个进程中分别有一段临界区关键代码,实现的功能都是不断的顺序输出0~9的字符。



    保证进程间同步

    [plain]

    #include <unistd.h>  

    #include <stdlib.h>  

    #include <stdio.h>  

    #include <sys/types.h>  

    #include <sys/ipc.h>  

    #include <sys/sem.h>  

      

    static int init_semvalue (int);  

    static void del_semvalue (int);  

    static int P (int);  

    static int V (int);  

      

    //自己定义的semun结构体  

    union semun  

    {  

      int val;  

      struct semid_ds *buf;  

      unsigned short *array;  

      struct seminfo *__buf;  

    };  

      

    int  

    main (int argc, char *argv[])  

    {  

      int var_cri = 0;  

      int sem_id;  

      pid_t pid;  


      //创建一个信号量  

      sem_id = semget ((key_t) 2234, 1, 0666 | IPC_CREAT);  

      //初始化一个信号量  

      if (!init_semvalue (sem_id))  

        {  

          fprintf (stderr, "Failed to initialize semaphore!\n");  

          exit (EXIT_FAILURE);  

        }  

      //创建子进程  

      if ((pid = fork ()) == 0) //子进程  

        {  

          while (1)  

        {  

              //临界区  

          if (!P (sem_id))//申请资源  

            exit (EXIT_FAILURE);  

          int i;  

          for (i = 0; i != 10; ++i)  

            {  

              printf ("[child]: %d\n", i);  

              sleep (1);  

            }  

          if (!V (sem_id))//释放资源  

            exit (EXIT_FAILURE);  

        }   

        }  

      else if (pid > 0)      //父进程  

        {  

          sleep (2);  

          while (1)  

        {  

              //临界区  

          if (!P (sem_id))  

            exit (EXIT_FAILURE);  

          int i;  

          for (i = 0; i != 10; ++i)  

            {  

              printf ("[parent]: %d\n", i);  

              sleep (1);  

            }  

          if (!V (sem_id))  

            exit (EXIT_FAILURE);  

        }  

          sleep (8);  

          //销毁信号量  

          del_semvalue (sem_id);  

        }  

      exit (EXIT_SUCCESS);  

    }  

      

      

    static int  

    init_semvalue (int id)  

    {  

      union semun sem_union;  

      sem_union.val = 1;  

      if (semctl (id, 0, SETVAL, sem_union) == -1)//设置信号量集中的信号量值value  

        return (0);  

      return (1);  

    }  

      

    static void  

    del_semvalue (int id)  

    {   

      union semun sem_union;  

      if (semctl (id, 0, IPC_RMID, sem_union) == -1)//IPC——RMID将信号量集从内存中删除  

        fprintf (stderr, "Failed to delete semaphore\n");  

    }  

      

    int  

    P (int id)  

    {  

      struct sembuf op;  

      

      op.sem_num = 0;//单信号  

      op.sem_op = -1;//P操作  

      op.sem_flg = 0;  

      if (semop (id, &op, 1) < 0)//改变key,它代表进程要使用的某个资源  

        return 0;  

      return 1;  

    }   

      

    int  

    V (int id)  

    {  

      struct sembuf op;  

      

      op.sem_num = 0;  

      op.sem_op = 1;//V操作  

      op.sem_flg = 0;  

      if (semop (id, &op, 1) < 0)  

        return 0;  

      return 1;  

    }  
    重要聲明:本論壇是以即時上載留言的方式運作,比思論壇對所有留言的真實性、完整性及立場等,不負任何法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,讀者及用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,讀者及用戶應尋求專業意見(如涉及醫療、法律或投資等問題)。 由於本論壇受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者及用戶發現有留言出現問題,請聯絡我們比思論壇有權刪除任何留言及拒絕任何人士上載留言 (刪除前或不會作事先警告及通知 ),同時亦有不刪除留言的權利,如有任何爭議,管理員擁有最終的詮釋權。用戶切勿撰寫粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。

    手機版| 廣告聯繫

    GMT+8, 2024-9-28 03:19 , Processed in 0.025464 second(s), 27 queries , Gzip On.

    Powered by Discuz! X2.5

    © 2001-2012 Comsenz Inc.

    回頂部