1. 程式人生 > >訊號量實現多程序的同步訪問

訊號量實現多程序的同步訪問

Comm.h檔案

#ifndef _COMM_H_

#define _COMM_H_

#include<stdio.h>

#include<stdlib.h>

#include<error.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

#include<unistd.h>

#define PATHNAME "."

#define PROJ_ID 06666

typedef union semun {

int val;

struct semid_ds *buf;

unsigned short *array;

struct seminfo *__buf;

void *__pad;

}my_semun;

int Creat_sems(int nsems);

int Init_sems(int semid,int which,int _val);

int Get_sems();

int Destroy_sems(int semid,int sennum);

int P(int semid);

int V(int semid);

#endif

comm.c檔案

#include"comm.h"

static Comm_sems(int nsems,int flags)

{

key_t key = ftok(PATHNAME, PROJ_ID);

int semid = semget(key,nsems,flags);

if(semid < 0)

{

perror("semget");

}

return semid;

}

int Creat_sems(int nsems)//建立訊號量

{

return Comm_sems(nsems,IPC_CREAT | IPC_EXCL | 0666);

}

int Init_sems(int semid,int which,int _val)//初始化訊號量

{

my_semun _semun;

_semun.val = _val;

if(semctl(semid,which,SETVAL,_semun)<0)//初始化訊號量函式

{

perror("Init_sems");

return -1;

}

return 0;

}

int Get_sems()//獲取訊號量semid

{

return Comm_sems(0,IPC_CREAT);

}

int Destroy_sems(int semid, int semnum)//銷燬訊號量

{

if(semctl(semid,semnum,IPC_RMID) < 0)//銷燬訊號量函式

    {

return -1;

}

return 0;

}

static comm_semop(int semid,int which)

{

struct sembuf sbuf;

sbuf.sem_num = 0;

sbuf.sem_op = which;

sbuf.sem_flg = SEM_UNDO;

if(semop(semid,&sbuf,1)<0)//訊號量操作函式

{

perror("semop");

return -1;

}

return 0;

}

int P(int semid)//P操作

{

comm_semop(semid,-1);

}

int V(int semid)//V操作

{

comm_semop(semid,1);

}

mysem.c檔案

#include"comm.h"

int main()//測試

{

int semid = Creat_sems(1);//建立訊號量

Init_sems(semid,0,1);//初始化訊號量

if(fork() == 0){//child

int _semid = Get_sems();//子程序獲取semid

int count = 30;

while(count--){

P(_semid);//P操作

printf("A");

fflush(stdout);

usleep(231451);

printf("A");

fflush(stdout);

usleep(131451);

V(_semid);//V操作

}

}

else//father

{

int count = 30;

while(count--){

P(semid);//P操作

printf("B");

fflush(stdout);

usleep(131451);

printf("B");

fflush(stdout);

usleep(231451);

V(semid);//V操作

}

wait(NULL);

}

Destroy_sems(semid,0);//刪除訊號量

//訊號量的生命週期是隨核心的

return 0;

}

接下來我們來編寫Makefile檔案

mysem:comm.c mysem.c

gcc -o [email protected] $^

.PHONY:clean

clean:

rm -f mysem

完成上述程式碼後讓我們來看看結果

由結果可見我們的程式碼採用訊號量實現了多程序的同步訪問的功能,下面讓我們來深入瞭解一下訊號量有關的操作函式

(1)int semget(key_t key, int nsems, int semflg)

key:第一個引數key一般是系統呼叫 key_t ftok(const char *pathname, int proj_id);

函式來獲取的具體用法可以參考上面的程式碼.

nsems:第二個引數指出了一個新的訊號量集中應該建立訊號量的個數

semflg:IPC_CREAT如果訊號量集在系統核心中不存在,則建立訊號量集。IPC_EXCL當和 IPC_CREAT一同使用時,如果訊號量集已經存在,則呼叫失敗。如果單獨使用IPC_CREAT,則semget()要麼返回新建立的訊號量集的識別符號,要麼返回系統中已經存在的同樣的關鍵字值的訊號量的識別符號。如果IPC_EXCL和IPC_CREAT一同使用,則要麼返回新建立的訊號量集的識別符號,要麼返回-1,所以IPC_EXCL和IPC_CREAT一同使用返回的訊號量一定是新建立的。IPC_EXCL單獨使用沒有意義。

返回值:成功返回semid,失敗返回-1。

(2)int semctl(int semid, int semnum, int cmd, ...)

semid:訊號量的標識碼,semget()函式的返回值

semnum:操作訊號在訊號集中的編號,第一個訊號量的編號為0

cmd:引數cmd中可以使用的命令如下(以下資訊由百度搜索獲得):

IPC_STAT讀取一個訊號量集的資料結構semid_ds,並將其儲存在semun中的buf引數中。

IPC_SET設定訊號量集的資料結構semid_ds中的元素ipc_perm,其值取自semun中的buf引數。

IPC_RMID將訊號量集從記憶體中刪除。

GETALL用於讀取訊號量集中的所有訊號量的值。

GETNCNT返回正在等待資源的程序數目。

GETPID返回最後一個執行semop操作的程序的PID。

GETVAL返回訊號量集中的一個單個的訊號量的值。

GETZCNT返回這在等待完全空閒的資源的程序數目。

SETALL設定訊號量集中的所有的訊號量的值。

SETVAL設定訊號量集中的一個單獨的訊號量的值。

上述程式碼中我們採用semctl()函式刪除了訊號量以及初始化。

採用semctl刪除訊號量我們只需將IPC_RMID引數傳遞給cmd。

採用semctl初始化訊號量時第三個引數需要設定為SETVAL;此時還需要第四個引數union semun,具體用法可以參看上面的程式碼。

返回值:成功返回0,失敗返回-1.

(3)int semop(int semid, struct sembuf *sops, unsigned nsops)

semid:訊號量的標識碼

sops:sops是一個指向結構體陣列的指標。

 struct   sembuf{

     unsigned short  sem_num;//第幾個訊號量,第一個訊號量為0;

     short  sem_op;//對該訊號量的操作。

     short _semflg;

};

_semflg:訊號操作標誌,可能的選擇有兩種

IPC_NOWAIT // 對訊號的操作不能滿足時, semop() 不會阻塞,並立即返回,同時設定錯誤資訊。

SEM_UNDO // 程式結束時 ( 不論正常或不正常 ) ,保證訊號值會被重設為 semop() 呼叫前的值。這樣做的目的在於避免程式在異常情況下結束時未將鎖定的資源解鎖, 造成該資源永遠鎖定。

nsops:操作結構的數量,恆大於或等於1

返回值:成功返回0失敗返回-1

這三個函式的標頭檔案為:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

相關推薦

訊號實現程序同步訪問

Comm.h檔案 #ifndef _COMM_H_ #define _COMM_H_ #include<stdio.h> #include<stdlib.h> #include<error.h> #include<sys/types

【Linux】執行緒總結:執行緒同步 -互斥鎖,條件變數,訊號實現生產者消費者模型

學習環境 :  Centos6.5 Linux 核心 2.6 Linux執行緒部分總結分為兩部分:(1)執行緒的使用 ,(2)執行緒的同步與互斥。 第一部分執行緒的使用主要介紹,執行緒的概念,建立執行緒,執行緒退出,以及執行緒的終止與分離。【完

semget函式 semopt 採用訊號處理程序互斥同步

採用訊號量處理多程序互斥同步       訊號量與訊息類似,也是程序間通訊的一種方法。我們在這裡講的訊號量,實際上是一個包含訊號量元素陣列的訊號量集。訊號量元素與E.W.Dijkstra提出的整數訊號量相對應。在一個單系統呼叫中,程序可在完整的訊號量集上操作。       訊

Python程序,同步互斥,訊號,鎖補充上一篇文章

from multiprocessing import Event,Process from time import sleep def wait_event1(): print("1想操作臨界區資源") e.wait() print("1開始操作臨界區資源",e.is_set()

簡單應用訊號實現程序同步控制

               --------參考文獻   W.Richard Stevens, Stephen A.Rago.UNIX環境高階程式設計[M].北京:人民郵電出版社,2014.6:45

訊號 實現程序互斥與同步

訊號量基本術語 現代計算機系統中,多個程序可以併發執行,程序間必然存在共享資源和相互合作的問題。 同步主要是使用者多個程序相互協作,共同完成任務,是程序間的直接制約問題;互斥則主要是為了多個程序分時使用有限的資源。 訊號量(semaphore)是1965

執行緒同步3 ------ 訊號實現程序或者執行緒之間的同步

基本概念       首先要注意,訊號量和訊號是完全兩碼事。訊號量是一個計數器,常用於處理程序或執行緒的同步問題,特別是對臨界資源訪問的同步。臨界資源可以簡單地理解為在某一時刻只能由一個程序或執行緒進行操作的資源。通常,程式對共享資源的訪問的程式碼只是很短的一段,但就是這一

Linux利用訊號實現執行緒的同步與互斥

執行緒使用互斥鎖可以實現執行緒間的互斥,而互斥鎖本身就是對資源的一種標識狀態,當可以申請到鎖時說明此時資源可以使用,當申請鎖失敗時說明資源此時被其他執行緒所佔用不可使用,我們可以使用訊號量來代替互斥鎖實現。 訊號量用來表示資源數目,當一個執行緒要去訪問資源時,必須先去申請

linux執行緒程式設計(C):訊號實現的執行緒安全佇列

用訊號量實現的執行緒安全佇列。 簡單有用的示例程式, 比起互斥量的實現在多執行緒時效率更好。 cir_queue.h /* * \File * cir_queue.h * \Brief * circular queue */#ifndef __CIR_QUEUE_H_

訊號:整型、記錄型訊號以及利用訊號實現程序互斥和前驅關係

訊號量機構是一種功能較強的機制,可用來解決互斥與同步的問題,它只能被兩個標準的原語wait(S)和signal(S)來訪問,也可以記為“P操作”和“V操作”。原語是指完成某種功能且不被分割不被中斷執行的操作序列,通常可由硬體來實現完成不被分割執行特性的功能。如前述的“Tes

IOS執行緒使用GCD與訊號實現生產者與消費者模式

一、原理的簡述   在生產者消費者模式當中,首先需要分清在這個模式當中有哪些角色? 各角色分別擔任什麼職責與它們之間的關係如何? 角色之間是在保證資料的準確性的情況下如何通訊(同步資料)的? 假設現在有一個這樣的情形: 有兩個人共同訪問一個容量有限的倉庫,這2個人,

【ASP.NET】UCenter實現站點同步註冊

res login oct bst center 實現 log conf https 問題描述 上一篇文章寫了【ASP.Net】UCenter實現多站點同步登錄退出 在整合論壇的時候,同步註冊也是相當必要的一個功能:將論壇註冊的用戶同步到自己的網站,自己網站註冊

python socket 套接字編程 單進程服務器 實現客戶端訪問

host port list 不能 ioerror 存儲 utf8 所有 tin 服務器: 1 import socket 2 #單進程服務器 實現多客戶端訪問 IO復用 3 #吧所有的客戶端套接字 放在一個列表裏面,一次又一次的便利過濾 4 #這就是apache

Linux c++,用訊號實現消費者生產者佇列(程式碼可直接通過編譯)

//用訊號量實現的一個消費者生產者佇列, #include <iostream> #include <pthread.h> #include <semaphore.h> #include <errno.h> #include <queue>

python語法——使用Pool實現程序並行

簡介 Pool 模組來自於 multiprocessing 模組。 multiprocessing 模組是跨平臺版本的多程序模組,像執行緒一樣管理程序,與 threading 很相似,對多核CPU的利用率會比 threading 好的多。 Pool 類可以提供指定數

互斥程序,單程序不同執行緒間使用

直接上程式碼了: #include <stdio.h> #include <stdlib.h> #include <Windows.h> int main() { /* 第二個引數:TRUE在建立互斥量之後立馬擁有該互斥量,

python技巧——使用Pool實現程序並行

簡介 可以使用 Pool來實現多程序並行。 Pool 模組來自於 multiprocessing 模組。 multiprocessing 模組是跨平臺版本的多程序模組,像執行緒一樣管理程序,與 threading 很相似,對多核CPU的利用率會比 threading

程序與執行緒(2)- python實現程序

python 實現多程序  參考連結: https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/ python中實現多程序的模組:multiprocessing 注意:在windows系統下

執行緒與程序及Python實現【Python實現程序

上一篇部落格介紹了多執行緒與多程序的理論部分,這篇部落格將參考部落格以及各種教程完成Python多程序實現部分。 multiprocessing模組 Process 類 multiprocessing.Process(group=None, target=N

python3實現程序併發任務

在python開發中,有時候會有這樣的需求,比如說我後很多個任務,需要並行執行,也就是說有一個任務佇列,大家都知道,在python中的多執行緒,它其實從嚴格意義上來講,並不是真正的多執行緒。所以用多執行緒我們還不如使用多程序。使用多程序的有什麼好處了,它可以實現分散式多機並行。多個客戶端共享一個