1. 程式人生 > >linux下c程式設計之訊號量semget,semop,semctl函式

linux下c程式設計之訊號量semget,semop,semctl函式

訊號量

今天去參加北京市的植樹志願者活動啦!早上起來的挺早的,610就被傑子給叫起來啦,帶著對春天的嚮往,我們坐著不花錢的大巴去做為市領導服務去啦!發了一個小紅帽還有一個紅色的制服。

唉。。。說好了,早上9點多學學校的,結果下午四點到的學校,專業課給耽誤了。不過今天的收穫還是蠻多的,還親自為了後代埋了兩顆小樹苗呢,哈哈。。。

現在我們就談談訊號量吧,再沒有講這個之前,我就預習了一下訊號量,所以待明天老師再一講,我就能更理解它的真正含義和作用啦!

訊號量(s):是一種特殊的變數,它的僅僅取正值,並且允許對訊號量的操作只有兩種:1、等待(wait

                                                  2

、傳送訊號(signal

wait操作:如果S大於零,wait就在一個原子操作中測試S,並對其進行減量運算;

如果S等於零,wait就在一個原子操作中測試S,並阻塞呼叫程式。

signal操作:如果有執行緒在訊號量上阻塞,S就等於零,signal就會解除對某個等待執行緒的阻塞;

如果沒有執行緒在訊號量上阻塞,signal就對S進行增量運算。

訊號量分為:核心訊號量和使用者態程序使用訊號量

POSIX訊號量又分為:有名訊號量和無名訊號量、

他們之間的區別近似與有名管道與無名管道。

有名訊號量,其值儲存在檔案中,所以它可以用於執行緒也可以用於程序間的同步。無名訊號量,其值儲存在記憶體中。

下面介紹一下,與訊號量有關的函式吧,主要應用到的函式有:

1.        Semget()

2.        Semop()

3.        Semctl()

其中,semget函式是為了獲取訊號量的標識碼的,然後其他的函式只能通過對semget的返回值對訊號量進行處理。

Semget()函式:

#include<sys/sem.h>

Int semget(key_t _key,int_nsems,int _semflg);

函式的功能:是建立一個訊號量或者是為了獲得一個新的鍵值

返回值:成功的返回訊號量的標識碼,如果函式呼叫失敗返回-1

第一個引數_key,為整型值,是允許其他的程序訪問訊號量的一個整型的變數。所以的訊號都是通過間接的方式獲得的,執行的程式會提供一個訊號的鍵值,系統為每一個鍵值賦予一個訊號量,其他的處理函式只能通過對semget

函式的返回值進行處理。

第二個引數_nsems,引數表示訊號量的編號,幾乎總是取值為1.

第三個引數_semflg,訊號量的許可權。

系統呼叫semget()的第一個引數是關鍵字值(一般是由系統呼叫ftok()返回的)。系統核心將此值和系統中存在的其他的訊號量集的關鍵字值進行比較。開啟和存取操作與引數semflg中的內容相關。IPC_CREAT如果訊號量集在系統核心中不存在,則建立訊號量集。IPC_EXCL當和 IPC_CREAT一同使用時,如果訊號量集已經存在,則呼叫失敗。如果單獨使用IPC_CREAT,則semget()要麼返回新建立的訊號量集的標識符,要麼返回系統中已經存在的同樣的關鍵字值的訊號量的識別符號。如果IPC_EXCLIPC_CREAT一同使用,則要麼返回新建立的訊號量集的標識符,要麼返回-1IPC_EXCL單獨使用沒有意義。引數nsems指出了一個新的訊號量集中應該建立的訊號量的個數。下面是一個開啟和建立訊號量的程式:

int mykey=5555;
int semid;
semid=semget(mykey,numsems,IPC_CREAT|0660);

if(semid==-1)

{

    perror("semget :");

      exit(1);

}
需要說明的是,返回一個訊號量的ID號。其他通過對訊號量的ID號進行操作。

semop()函式使用:

函式功能:使用者改變訊號量的值.

返回值:函式呼叫成功返回0,失敗返回-1

引數semid:系統分配給該訊號量的一個ID號,通過semget函式的返回值來獲得,也稱為訊號的標識碼

引數sops:一個指向訊號量結構體陣列的指標,訊號量的結構體至少有3個成員。

其結構如下:

struct sembuf

{

unsigned short sem_num;操作訊號在訊號集中的編號,第一個訊號的編號為0,第二個為1,一次後推

short sem_op;訊號資源,如果有就分配,如果為負值就等待(wait),如果正值就分配訊號資源

short sem_flg;訊號操作標誌,有兩種狀態,一個是SEM_UNDO,另一個是SEM_NOWAIT

}

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

SEM_UNDO//程式結束時(無論是否正常結束),保證訊號值會被重新設為semop()呼叫前的值。這樣做

的目的在於避免在異常情況下結束時未將鎖定資源解鎖,造成該資源永遠鎖定。

下面寫一個小例子宣告一個結構體:

 struct sembuf sem1_opt_wakeup[1]={0,1,SEM_UNDO};

 struct sembuf sem1_opt_wait[1]={1,-1,SEM_UNDO};
semctl()函式:

功能:控制訊號量的資訊

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

第一個引數semid:訊號量標識碼,還是通過semget來獲得的,是semget函式的一個返回值

第二個引數semnum:訊號量的編號,當用到訊號量陣列的時候,這個編號就會起到作用

第三個引數cmd:為允許的命令,其範圍在:

第四個引數union semun:是一個共同體

結構如下:

union semun{

int val;

struct semid_ds *buf;

unsigned short *array;

下面看一個訊號量的使用圖解:

下面看一個小案例吧,來說明一下訊號量的使用,這裡我們用到了兩個程序,也就是要寫兩個函式,也用到了共享記憶體的知識。

程序1:/*
* filename:shm
*
*/
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/stat.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<fcntl.h>
#include<stdlib.h>
#include<time.h>
#include<stdio.h>
#include<string.h>
#define SEM_KEY1 5555
union semun
{
 int setval;
 struct semid_ds *buf;
 unsigned short *array;
};
int main()
{
 int shmid,semid;
 int *addr;
 int h=0,w=0;
 int ret;
 union semun sem_args;
 unsigned short array[2]={1,1};
 sem_args.array=array;
 shmid=shmget(ftok("/etc/passwd",1001),getpagesize(),IPC_CREAT|IPC_EXCL|S_IRUSR| S_IWUSR| S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
  if(shmid==-1)
        {
                perror("shmget error:");
                exit(EXIT_FAILURE);
        }
 semid=semget(SEM_KEY1,2,IPC_CREAT|0600);
 if(semid==-1)
        {
                perror("semget error:");
                exit(EXIT_FAILURE);
        }
 ret=semctl(semid,1,SETALL,sem_args);
 if(ret==-1)
 {
  perror("shmctl error:");
  exit(EXIT_FAILURE);
 }
 struct sembuf sem1_opt_wakeup[1]={0,1,SEM_UNDO};
 struct sembuf sem2_opt_wait[1]={1,-1,SEM_UNDO};

 while(1)
 {
  int i=0;
  semop(semid,sem2_opt_wait,1);
  addr=shmat(shmid,0,0);
  printf("please input your infornation:\n");
  scanf("%d%d",addr,addr+1);
  shmdt(addr);
  semop(semid,sem1_opt_wakeup,1);
  printf("退出清輸入1\n");
  scanf("%d",&i);
  if(i==1)
  {
    shmctl(shmid,IPC_RMID,NULL);
                        semctl(semid,IPC_RMID,NULL);
   exit(1);
  }
 }
return 0;
}
程序2:

#include<sys/types.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#define SEM_KEY 5555

int main()
{
 int shmid,semid;
 int *addr;
 int h,w;
 float result,sum;
 struct sembuf sem1_opt_wait[1]={0,-1,SEM_UNDO};
        struct sembuf sem2_opt_wakeup[1]={1,1,SEM_UNDO};

 while(1)
 {
  shmid=shmget(ftok("/etc/passwd",1001),getpagesize(),S_IRUSR| S_IWUSR| S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
  sleep(1);
  if(shmid==-1)
         {
                 perror("shmget error:");
                 exit(EXIT_FAILURE);
         }
  semid=semget(SEM_KEY,2,0600);
  if(semid==-1)
         {
                 perror("semget error:");
                 exit(EXIT_FAILURE);
         }
         addr=shmat(shmid,0,0);
  w=*(addr+1);
  h=*addr;
  sum=h*h/10000;
  result=w/sum;
  
  semop(semid,sem1_opt_wait,1);
   
  if(result>25)
  {
   printf("胖拉!\n");
   *(addr+2)=0;
  }
  else if(result<20)
  {
   printf("瘦啦!\n");
   *(addr+2)=0;
  }
  else
  {
   if(result>5&&result<20)
   {
    printf("正常!\n");
    *(addr+2)=0;
   }
  }
  shmdt(addr);
  semop(semid,sem2_opt_wakeup,1);
  sleep(2);
 }
}

相關推薦

linuxc程式設計訊號semgetsemopsemctl函式

訊號量 今天去參加北京市的植樹志願者活動啦!早上起來的挺早的,6:10就被傑子給叫起來啦,帶著對春天的嚮往,我們坐著不花錢的大巴去做為市領導服務去啦!發了一個小紅帽還有一個紅色的制服。 唉。。。說好

Linux程序間通訊:訊號 semget()、semop()、semctl()

這篇文章將講述別一種程序間通訊的機制——訊號量。注意請不要把它與之前所說的訊號混淆起來,訊號與訊號量是不同的兩種事物。有關訊號的更多內容,可以閱讀我的另一篇文章:Linux程序間通訊 -- 訊號。下面就進入訊號量的講解。 一、什麼是訊號量 為了防止出現

嘗試linuxc程式設計管道

今天試了下管道,感覺挺有意思的~ 現在才發現,原來程序也有這麼多的功能可以實現。管道分類: 根據程序的相互關係,可以分為:匿名管道與命名管道。1   匿名管道:管道是父程序和子程序間,或是子程序與子程序間單向的通訊機制,即一個程序傳送資料到管道,另外一個程序從管道中讀出資料。

linuxc程式設計gdb除錯

之前在個人微信公眾號寫了一篇關於linux下c程式設計之gcc編譯的文章,感興趣可關注我的個人微信公眾號,搜尋移動開發與網路安全技術棧加關注,或掃描本文末尾的微信二維碼加關注。 今天接著說下linu

System V訊號-semget()、semop()和semctl()

簡單介紹 這是我開這個欄目的第一篇文章,順序也不是按照《Unix網路程式設計》(以下簡稱網編)的章節順序往下寫的,可能文章會提及一些前面章節的概念,遇到的話,我會做一些引導,讀者也可以自己找找相關的內容或書籍檢視。 訊號量是一種用於提供不同程序間或一個給定程

linux程序控制訊號 semgetsemctlsemop

轉載自 https://www.cnblogs.com/52php/p/5851570.html 這篇文章將講述別一種程序間通訊的機制——訊號量。注意請不要把它與之前所說的訊號混淆起來,訊號與訊號量是不同的兩種事物。有關訊號的更多內容,可以閱讀我的另一篇文章:L

linuxC 程式設計學習多程序程式設計(一)

一、程序概念 程序是作業系統中資源分配的最小單位,而執行緒是排程的最小單位。 一個程序,主要包含三個元素: a)        一個可以執行的程式; b)        和該程序相關聯的全部資料(包括變數,記憶體空間,緩衝區等等); c)        程式的執行上下文(

linuxC程式設計(六) void用法大總結

這次對void差不多有點多少的理解了,從最初的理解就是空,麼有的意思。首先void是C語言中的關鍵字,對函式返回值的限定,對函式引數的限定。 1.void*常常被稱為空指標,其實理解為指向任意型別的指標比較合適,as we all kown,如果指標p1和指標p2的型別相同

linux 多執行緒訊號 sem_init

1. 什麼是訊號量 linux sem 訊號量是一種特殊的變數,訪問具有原子性, 用於解決程序或執行緒間共享資源引發的同步問題。 使用者態程序對 sem 訊號量可以有以下兩種操作: 等待訊號量 當訊號量值為 0 時,程式等待;當訊號量值大於 0 時,訊號量減 1,程式

LINUXC++程式設計如何獲得某程序的ID

#include <stdio.h> #include <stdlib.h> #include <unistd.h> using namespace std; pid_t getProcessPidByName(const char *proc_name) {

linuxshell 程式設計擴充套件正則表示式

1. ‘+’ 限定字元 +限定符表示前面字元至少出現一次或者多次。與*不同在於0次或者多次 2. '?' 限定符 ?限定前面的字元最多出現一次。即出現0次或者1次 3. 數線 |和圓括號() 例如

linuxC程式設計詳解

linux作業系統下 c語言程式設計 整理編寫:007xiong原文:Hoyt等(一)目錄介紹1)Linux程式設計入門--基礎知識2)Linux程式設計入門--程序介紹3)Linux程式設計入門--檔案操作4)Linux程式設計入門--時間概念5)Linux程式設計入門--訊號處理6)Linux程式設計入

Linux程序間通訊訊號(semaphore)、訊息佇列(Message Queue)和共享記憶體(Share Memory)

System V 程序通訊方式:訊號量(semaphore)、訊息佇列(Message Queue)和共享記憶體(Share Memory) 訊號量 訊號量(semaphore)實際是一個整數,它的值由多個程序進行測試(test)和設定(set)。就每個程序所關心的測試和

linuxc程式設計常識

主要內容: ① 標準 (ANSI C, POSIX, SVID, XPG, ...) ② 函式庫和系統呼叫 ③ 線上文件 (man, info, HOW-TO, ...) ④ C 語言程式設計風格 ⑤ 庫和標頭檔案的儲存位置 ⑥ 共享庫及其相關配置 一: 標準 (ANSI C, POSIX, SVID, X

linux shell 程式設計變數及數學運算

1.shell中的變數是不分資料型別的,統一按照字串來儲存 2. bash shell只能支援數學整數運算(zsh可以支援浮點) 3.以下都是在bash shell 下進行的數學運算 方法一使用方括號進行基本的整數運算: #!/bin/bash var1=1 var2=2

Linuxsocket程式設計多執行緒TCP伺服器

程式碼如下: thread_server.c #include<string.h> #include<stdlib.h> #include<stdio.h> #include<sys/types.h> #i

Linux核心同步機制訊號和互斥體

訊號量:訊號量(semaphore)是程序間通訊處理同步互斥的機制。是在多執行緒環境下使用的一種措施,它負責協調各個程序,以保證他們能夠正確、合理的使用公共資源。 它和spin lock最大的不同之處就是:無法獲取訊號量的程序可以睡眠,因此會導致系統排程。原理訊號量一般可以用

Linuxsocket程式設計多程序TCP伺服器端

程式碼如下: tcp_server.c #include<string.h> #include<stdlib.h> #include<stdio.h> #include<sys/types.h> #includ

Linuxsocket程式設計UDP簡單實現

本文實現一個簡單的UDP小例子,來說明Linux下socket程式設計之UDP的簡單實現。本文主要包括三個部分:伺服器端的實現,客服端的實現和通訊測試。實現的功能:客服端傳送一條訊息給伺服器端,伺服器

LinuxC程式設計-----IO/檔案操作/記憶體對映 實現簡單記錄儲存(3)

利用linux下的檔案記憶體對映可以實現程序共享資料,我們可以把一個檔案對映到虛擬記憶體中使多個程序進行共享, 到這裡我們大概能想到他能應用到的領域 是很廣泛的  主要涉及到 mmap  munmap   msync 三個函式的應用 下面貼程式碼  下面一段程式碼是為檔案