1. 程式人生 > >Linux 下程序間通訊機制(六) 訊號燈集 Semaphore Arrays

Linux 下程序間通訊機制(六) 訊號燈集 Semaphore Arrays

訊號燈集函式定義如下:


#include <sys/sem.h>
int semctl(int sem_id, int sem_num, int command, ...);
int semget(key_t key, int num_sems, int sem_flags);
int semop(int semid, struct sembuf *sops, unsigned nsops);




semget函式建立一個新的訊號量或是獲得一個已存在的訊號量鍵值。
semop函式用來改變訊號量的值(包含P操作和V操作)。
semctl函式允許訊號量資訊的直接控制(包含初始化訊號燈和刪除訊號燈)。




事實上,為了獲得我們特定操作所需要的#define定義,我們需要在包含sys/sem.h檔案之前通常需要包含sys/types.h與sys/ipc.h檔案。




相關的型別定義:


struct  sembuf{
  unsigned short sem_num;  /* semaphore number *//*訊號燈在訊號燈集中的編號*/
  short          sem_op;   /* semaphore operation *//*P操作或者V操作*/
  short          sem_flg;  /* operation flags */
};



//這個聯合體需要在程式宣告,用於semctl函式的SETVAL選項的傳值,作為第四個引數。
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
}

demo

程序間利用共享記憶體機制通訊,一個程序寫,一個程序讀,用訊號燈同步。

//writer.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define R 0
#define W 1
#define N 1024

union semun {
         int              val;    /* Value for SETVAL */
         struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
         unsigned short  *array;  /* Array for GETALL, SETALL */
         struct seminfo  *__buf;
};

void pv(int semid, int op, int num)
{
    struct sembuf buf;
    buf.sem_num = num;//訊號燈編號
    buf.sem_op = op;  //p操作或者v操作
    buf.sem_flg = 0;
 /*semid為訊號燈集id, buf為struct sembuf結構體指標, 1表示操作訊號燈的個數為1,如果大於一,表示操縱多個(則buf為struct sembuf結構體的陣列指標)*/
    if (semop(semid, &buf, 1) == -1)
    {
        perror("semop");
        exit(-1);
    }    
}

int main()
{
    int semid, shmid;
    key_t key;
    char *shmaddr;
   
    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(-1);
    }
    //先啟動的程序負責進行初始化,訊號燈集中由兩個訊號燈,一個為讀,一個為寫
    if ((semid = semget(key, 2, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
    {
        if (errno == EEXIST)
        {
            semid = semget(key, 2, 0666);
        }
    }
    else    //first
    {
        union semun un;

        un.val = 0;
        //讀的訊號燈值為0
        if (semctl(semid, R, SETVAL, un) == -1)
        {
            perror("init R");
            exit(-1);
        }
	 //寫的訊號燈值為1
        un.val = 1;
        if (semctl(semid, W, SETVAL, un) == -1)
        {
            perror("init R");
            exit(-1);
        }
    }
    //建立共享記憶體
    if ((shmid = shmget(key, N, 0666 | IPC_CREAT)) == -1)
    {
        perror("shmget");
        exit(-1);
    }
    //對映共享記憶體
    if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)
    {
        perror("shmaddr");
        exit(-1);
    }

    while (1)
    {
        //p(w) fgets v(r)
        
	 pv(semid, -1, W);
        fgets(shmaddr, N, stdin);
        pv(semid, 1, R);
        if (strncmp(shmaddr, "quit", 4) == 0)
            break;
    }

    usleep(100000);

    if(semctl(semid, 0, IPC_RMID) == -1)
    {
        perror("rm sem");
        exit(-1);
    }

    if (shmdt(shmaddr) == -1)
    {
        perror("shmdt");
        exit(-1);
    }

    if (shmctl(shmid, IPC_RMID, NULL) == -1)
    {
        perror("shmctl");
        exit(-1);
    }

    exit(0);
}


//reader.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define R 0
#define W 1
#define N 1024

union semun {
         int              val;    /* Value for SETVAL */
         struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
         unsigned short  *array;  /* Array for GETALL, SETALL */
         struct seminfo  *__buf;
};

void pv(int semid, int op, int num)
{
    struct sembuf buf;
    buf.sem_num = num;
    buf.sem_op = op;
    buf.sem_flg = 0;

    if (semop(semid, &buf, 1) == -1)
    {
        perror("semop");
        exit(-1);
    }    
}

int main()
{
    int semid, shmid;
    key_t key;
    char *shmaddr;

    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(-1);
    }

    if ((semid = semget(key, 2, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
    {
        if (errno == EEXIST)
        {
            semid = semget(key, 2, 0666);
        }
    }
    else    //first
    {
        union semun un;

        un.val = 0;
        if (semctl(semid, R, SETVAL, un) == -1)
        {
            perror("init R");
            exit(-1);
        }

        un.val = 1;
        if (semctl(semid, W, SETVAL, un) == -1)
        {
            perror("init R");
            exit(-1);
        }
    }

    if ((shmid = shmget(key, N, 0666 | IPC_CREAT)) == -1)
    {
        perror("shmget");
        exit(-1);
    }

    if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)
    {
        perror("shmaddr");
        exit(-1);
    }

    srandom(getpid());
    while (1)
    {
        //p(r) printf v(w)
        pv(semid, -1, R);
        printf("%s", shmaddr);
        if (strncmp(shmaddr, "quit", 4) == 0)
        {
            //v(r)
            pv(semid, 1, R);
            break;
        }
        pv(semid, 1, W);
        sleep(random()%5+1);
    }

    if (shmdt(shmaddr) == -1)
    {
        perror("shmdt");
        exit(-1);
    }

    exit(0);
}


相關推薦

Linux 程序通訊機制() 訊號燈 Semaphore Arrays

訊號燈集函式定義如下: #include <sys/sem.h> int semctl(int sem_id, int sem_num, int command, ...); int semget(key_t key, int num_sems, int sem

Linux程序通訊機制詳解

linux下程序間通訊的幾種主要手段:        1.管道(Pipe)及有名管道(named pipe):管道可用於具有親緣關係程序間的通訊,有名管道克服了管道沒有名字的限制,因此,除具有管道所具

Linux程序通訊方式 - UNIX Domain Socket

概述 Linux下程序通訊方式有很多,比較典型的有套接字,平時比較常用的套接字是基於TCP/IP協議的,適用於兩臺不同主機上兩個程序間通訊, 通訊之前需要指定IP地址. 但是如果同一臺主機上兩個程序間通訊用套接字,還需要指定ip地址,有點過於繁瑣. 這個時候就需要用到UNIX Domain Sock

Linux程序通訊機制----訊息佇列

一、什麼是訊息 訊息(message)是一個格式化的可變長的資訊單元。訊息機制允許由一個程序給其它任意的程序傳送一個訊息。當一個程序收到多個訊息時,可將它們排成一個訊息佇列。 1、訊息機制的資料結構 (1)訊息首部 記錄一些與訊息有關的資訊,如訊息的型別、大小、

Linux 環境程序通訊) 套介面(轉)

轉自https://www.ibm.com/developerworks/cn/linux/l-ipc/part6/, 作者:鄭彥興一個套介面可以看作是程序間通訊的端點(endpoint),每個套介面的名字都是唯一的(唯一的含義是不言而喻的),其他程序可以發現、連線並且 與之通訊。通訊域用來說明套介面通訊的協

linux程序通訊的幾種主要方式簡介

      共享記憶體是執行在同一臺機器上的程序間通訊最快的方式,因為資料不需要在不同的程序間複製。通常由一個程序建立一塊共享記憶體區,其餘程序對這塊記憶體區進行讀寫。共享記憶體往往與其它通訊機制,如訊號量結合使用,來達到程序間的同步及互斥。  首先要用的函式是shmget,它獲得一個共享儲存識別符號。

Linux程序通訊方式

概述 Linux下程序通訊方式有很多,比較典型的有套接字,平時比較常用的套接字是基於TCP/IP協議的,適用於兩臺不同主機上兩個程序間通訊, 通訊之前需要指定IP地址. 但是如果同一臺主機上兩個程序間通訊用套接字,還需要指定ip地址,有點過於繁瑣. 這個時候就需要用到UNIX

Linux程序通訊方式之管道、訊號、共享記憶體、訊息佇列、訊號量、套接字

/* 1,程序間通訊 (IPC ) Inter-Process Communication   比較好理解概念的就是程序間通訊就是在不同程序之間傳播或交換資訊。 2,linux下IPC機制的分類:管道、訊號、共享記憶體、訊息佇列、訊號量、套接字 3,這篇主要說說管

Linux 程序通訊)共享記憶體

可以說, 共享記憶體是一種最為高效的程序間通訊方式, 因為程序可以直接讀寫記憶體, 不需要任何資料的複製。 為了在多個程序間交換資訊, 核心專門留出了一塊記憶體區, 這段記憶體區可以由需要訪問的程序將其對映到自己的私有地址空間。 因此, 程序就可以直接讀寫這一記憶體區而不需要

嵌入式linux網路程式設計,UNIX域套接字,AF_LOCAL,PF_LOCAL,PF_UNIX,,AF_UNIX,程序通訊機制

文章目錄 1,UNIX域套接字 2,UNIX域套接字模型 3,UNIX域套接字 --- 示例 3.1,net.h 3.2,client.c 3.3,sever.c 3.4,linklist.h 3.5,link

Linux環境程序通訊(五): 共享記憶體()(轉)

轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html, 作者:鄭彥興系統呼叫mmap()通過對映一個普通檔案實現共享記憶體。系統V則是通過對映特殊檔案系統shm中的檔案實現程序間的共享記憶體通訊。也就是說,每個共享記憶體區域對

Linux環境程序通訊(四) 訊號燈(轉)

轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/, 作者:鄭彥興訊號燈與其他程序間通訊方式不大相同,它主要提供對程序間共享資源訪問控制機制。相當於記憶體中的標誌,程序可以根據它判定是否能夠訪問某些共享資源,同時,程序也可以修改該標誌。除了用於訪

Linux環境程序通訊(二): 訊號()(轉)

從訊號傳送到訊號處理函式的執行完畢對於一個完整的訊號生命週期(從訊號傳送到相應的處理函式執行完畢)來說,可以分為三個重要的階段,這三個階段由四個重要事件來刻畫:訊號誕生;訊號在程序中註冊完畢;訊號在程序中的登出完畢;訊號處理函式執行完畢。相鄰兩個事件的時間間隔構成訊號生命週期的一個階段。 下面闡述四個事件的實

Linux程序通訊

程序間通訊就是在不同程序之間傳播或交換資訊。但是,我們知道程序是具有獨立性的,因此,程序之間不可能直接進行通訊。人們之間交流需要空氣作為介質,程序之間“交流”也需要一個媒介,那麼程序之間存在著什麼雙方都可以訪問的介質呢? 程序的使用者空間是互相獨立的,一般而言是不能互相訪問的,唯一的例

Linux環境程序通訊(四) 訊號燈

一、訊號燈概述訊號燈與其他程序間通訊方式不大相同,它主要提供對程序間共享資源訪問控制機制。相當於記憶體中的標誌,程序可以根據它判定是否能夠訪問某些共享資源,同時,程序也可以修改該標誌。除了用於訪問控制外,還可用於程序同步。訊號燈有以下兩種型別:二值訊號燈:最簡單的訊號燈形式,

Linux系統-程序通訊(訊息佇列-詳解)

Linux下程序間通訊方式: # 管道( pipe ):管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的程序間使用。程序的親緣關係通常是指父子程序關係。 # 有名管道 (named pipe) : 有名管道也是半雙工的通訊方式,但是它允許無親緣關係程序

Linux環境程序通訊(五) 共享記憶體(

系統呼叫mmap()通過對映一個普通檔案實現共享記憶體。系統V則是通過對映特殊檔案系統shm中的檔案實現程序間的共享記憶體通訊。也就是說,每個共享記憶體區域對應特殊檔案系統shm中的一個檔案(這是通過shmid_kernel結構聯絡起來的),後面還將闡述。 1、系統V共

Linux環境程式設計程序通訊機制理解

一、Linux系統呼叫主要函式 二、建立程序   1、建立子程序系統呼叫fork()   2、驗證fork()建立子程序效果   3、系統呼叫fork()與掛起系統呼叫wait() 三、模擬程序管道通訊 四、pipe()下生產者與消費者問題 總結 一、Linux系統呼叫主要函式 首先,認識一下Linux下系統

Linux程序通訊之管道通訊詳解

        在學習程序的時候,我們瞭解到了程序的獨立性:程序之間是相互獨立的,每個程序有自己的虛擬地址空間,並且虛擬地址空間通過頁表的對映,對映到屬於自己的實體記憶體上。並且各個程序之間互相不影響,執行自己的程式碼。    

Linux程序通訊(匿名管道命名管道)(共享記憶體,訊息佇列,訊號量)

目錄 程序間通訊的介紹 管道 匿名管道 原理: 程式碼實現 匿名管道特性 實現管道符 |  命名管道 命名管道特性 程式碼實現 管道讀寫規則 作業系統中ipc的相關命令 共享記憶體(重點) 生命週期: 程式碼實現 程式碼實現獲