日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Linux進程間共享信號量的實現(xiàn)(linux不同進程信號燈共享)

在Linux系統(tǒng)中,進程間的通信是非常常見的場景。其中,信號量是一種常用的進程間通信機制,它可以用來實現(xiàn)進程的同步和互斥。在多進程或多線程的環(huán)境中,控制進程之間的訪問同步和互斥是非常重要的,而信號量正是解決這一問題的有效機制。

本文將介紹Linux中進程間共享信號量的實現(xiàn)方法,包括信號量的定義、初始化、操作等,希望能夠幫助讀者深入理解信號量的知識,更好地應用它們進行進程間通信。

一、信號量的定義

信號量是一種用于同步進程和線程的機制,它主要用于控制進程的互斥和同步。在Linux系統(tǒng)中,信號量是由一個整形變量和一組信號量操作組成的。信號量變量的值表示當前資源的可用數(shù)目。當信號量的值為正數(shù)時,表示還有可用資源;當信號量的值為0時,表示所有資源都被占用;當信號量的值為負數(shù)時,表示有進程正在等待釋放資源。

在Linux系統(tǒng)中,信號量的定義如下:

“`

struct sembuf{

unsigned short sem_num; // 信號量編號

short sem_op; // 信號量操作

short sem_; // 操作標志

};

union semun{

int val; // 信號量初始值

struct semid_ds *buf; // IPC_STAT、IPC_SET 操作用緩存區(qū)

unsigned short *array; // SETALL、GETALL 操作用數(shù)組

};

int semget(key_t key, int nsems, int sem); // 創(chuàng)建或打開一個信號量

int semctl(int semid, int semnum, int cmd, union semun arg); // 對一個信號量或信號量執(zhí)行控制操作

int semop(int semid, struct sembuf *sops, unsign int nsops); // 執(zhí)行信號量操作

“`

二、信號量的初始化

在使用信號量進行進程間通信時,需要先創(chuàng)建或打開一個信號量,并進行初始化。在Linux中,信號量的初始化可以使用 semget() 函數(shù)和 semctl() 函數(shù)進行。

1.使用 semget() 函數(shù)創(chuàng)建信號量

(1)semget() 函數(shù)原型

“`

#include

#include

#include

int semget(key_t key, int nsems, int sem);

“`

(2)參數(shù)說明

key:用于標識信號集的key值。

nsems:創(chuàng)建的信號集的數(shù)量。

sem:信號集的訪問權限。

(3)函數(shù)返回值

成功:返回信號量集的標識符。

失敗:返回 -1 并設置 errno 來指示錯誤的類型。

(4)示例代碼

“`

#include

#include

#include

#include

int mn()

{

int semid;

key_t key = 1234;

semid = semget(key, 1, 0666 | IPC_CREAT);

if (semid == -1) {

perror(“semget”);

return -1;

}

printf(“succeed to create semaphore: %d\n”, semid);

return 0;

}

“`

上面的示例代碼使用 key 為 1234 創(chuàng)建了一個信號量,該包含了一個信號量。sem 的值被設置為 0666 | IPC_CREAT 來表示新創(chuàng)建的信號量,如果已經(jīng)存在該信號量,則直接打開該信號量。

2. 使用 semctl() 函數(shù)初始化信號量

使用 semctl() 函數(shù)初始化信號量時,可以設置信號量的值、操作等。semctl() 函數(shù)使用如下:

(1)semctl() 函數(shù)原型

“`

#include

#include

#include

int semctl(int semid, int semnum, int cmd, union semun arg);

“`

(2)參數(shù)說明

semid:信號量集的標識符。

semnum:對信號量中的第幾個信號量進行操作。

cmd:操作類型,包括如下:

– SETVAL:設置信號量集中的一個信號量的值。

– IPC_RMID:從內(nèi)核中刪除信號量。

arg:參數(shù)類型 union semun,可以是如下情況:

– val:val 成員用于 SETVAL 操作設置一個信號量或數(shù)組的值。

– buf:buf 成員用于 IPC_STAT 和 IPC_SET 操作,獲取或修改信號量的狀態(tài)信息。

– array:array 成員用于 SETALL 和 GETALL 操作,設置或獲取整個信號量數(shù)組的值。

(3)函數(shù)返回值

成功:返回信號量集的標識符。

失?。悍祷?-1 并設置 errno 來指示錯誤的類型。

(4)示例代碼

“`

#include

#include

#include

#include

int mn()

{

int semid;

key_t key = 1234;

union semun arg;

struct sembuf sembuf;

int val = 1;

semid = semget(key, 1, 0666 | IPC_CREAT);

if (semid == -1) {

perror(“semget”);

return -1;

}

arg.val = val;

if (semctl(semid, 0, SETVAL, arg) == -1) {

perror(“semctl”);

return -1;

}

printf(“succeed to initialize semaphore: %d\n”, semid);

return 0;

}

“`

上面的示例代碼創(chuàng)建一個 key 值為 1234 的信號量,包含了一個信號量。使用 SETVAL 操作設置該信號量的值為 1。如果初始化成功,則返回該信號量的標識符 semid。

三、信號量的操作

在信號量的中,可以對單個信號量進行操作,也可以對信號量中的所有信號量進行操作。信號量的操作主要包括加操作和減操作。在 Linux 平臺下,可以使用 semop() 函數(shù)完成對信號量的操作。

在使用 semop() 函數(shù)對信號量進行操作時,需要傳入一個結構體 sembuf 作為信號量操作的參數(shù),或者傳入多個 sembuf,以便一次執(zhí)行多個信號量操作。

(1)sembuf 結構體的定義

“`

struct sembuf {

unsigned short sem_num; // 信號量中的信號量編號

short sem_op; // 信號量操作

short sem_; // 操作標志

};

“`

sem_num:信號量中的信號量編號。

sem_op:信號量的操作,其中,信號量的操作可以為如下值之一:

– 正整數(shù):表示向信號量中增加信號量值;

– 負整數(shù):表示從信號量中減去信號量值;

– 0:表示讀取信號量中的值。

sem_:操作標志,可用于 IPC_NOWT 等標志的設置。

(2)semop() 函數(shù)原型

“`

#include

#include

#include

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

“`

(3)參數(shù)說明

semid:信號量的標識符。

sops:指向 sembuf 結構數(shù)組的指針,其中每一個 sembuf 結構體描述了一個信號量的操作。

nsops:sops 指向的 sembuf 結構體的數(shù)量。

(4)函數(shù)返回值

成功:返回 0。

失敗:返回 -1 并設置 errno 來指示錯誤的類型,如 EAGN 表示操作被阻塞,EINVAL 不能操作等等。

(5)信號量操作的示例代碼

下面的示例代碼展示了如何在兩個進程中對共享的信號量進行操作。兩個進程的實現(xiàn)方式分別是獲取和釋放共享資源。

之一個進程:

“`

#include

#include

#include

#include

#include

#include

const char *data = “hello, world”;

int p(int semid, int semnum)

{

struct sembuf sem_buf;

sem_buf.sem_num = semnum;

sem_buf.sem_op = -1; // 清空信號量

sem_buf.sem_ = SEM_UNDO; // 系統(tǒng)內(nèi)核在進程退出時恢復信號量

return semop(semid, &sem_buf, 1);

}

int v(int semid, int semnum)

{

struct sembuf sem_buf;;

sem_buf.sem_num = semnum;

sem_buf.sem_op = 1; // 加 1

sem_buf.sem_ = SEM_UNDO; // 系統(tǒng)內(nèi)核在進程退出時恢復信號量

return semop(semid, &sem_buf, 1);

}

int mn()

{

int semid;

key_t key = 1234;

pid_t pid;

union semun arg;

struct sembuf sembuf;

int val = 1;

semid = semget(key, 1, 0666 | IPC_CREAT);

if (semid == -1) {

perror(“semget”);

return -1;

}

arg.val = val;

if (semctl(semid, 0, SETVAL, arg) == -1) {

perror(“semctl”);

return -1;

}

pid = fork();

if (pid == -1) {

perror(“fork”);

return -1;

} else if (pid == 0) {

// 子進程

p(semid, 0);

printf(“child process get the semaphore, write data\n”);

write(STDOUT_FILENO, data, strlen(data));

sleep(1);

v(semid, 0);

printf(“child process release the semaphore\n”);

} else {

// 父進程

struct sembuf sem_buf;

sem_buf.sem_num = 0;

sem_buf.sem_op = -1; // 清空信號量

sem_buf.sem_ = SEM_UNDO; // 系統(tǒng)內(nèi)核在進程退出時恢復信號量

semop(semid, &sem_buf, 1);

printf(“parent process get the semaphore, read data\n”);

read(STDIN_FILENO, data, strlen(data));

v(semid, 0);

printf(“parent process release the semaphore\n”);

}

semctl(semid, 0, IPC_RMID, arg);

return 0;

}

“`

上面的代碼中,fork() 函數(shù)創(chuàng)建一個子進程,在子進程中利用信號量實現(xiàn)獲取和釋放共享資源的操作。在父進程中也是利用信號量控制讀取和釋放共享資源的操作。

四、

相關問題拓展閱讀:

  • linux進程間通訊的幾種方式
  • LINUX下系統(tǒng)編程,多進程間數(shù)據(jù)共享,即共享變量

linux進程間通訊的幾種方式

一。管道(pipe)

  管道是Linux支持的最初IPC方式,管道可分為無名管道,有名管道等。

 ?。ㄒ唬o名管道,它具有幾個特點:

  1) 管道是半雙工的,只能支持數(shù)據(jù)的單向流動;兩進程間需要通信時需要建立起兩個管道;

  2) 無名管道使用pipe()函數(shù)創(chuàng)建,只能用于父子進程或者兄弟進程之間;

  3) 管道對于通信的兩端進程而言,實質上是一種獨立的文件,只存在于內(nèi)存中;

  4) 數(shù)據(jù)的讀寫操作:一個進程向管道中寫數(shù)據(jù),所寫的數(shù)據(jù)添加在管道緩沖區(qū)的尾部;另一個進程在管道中緩沖區(qū)的頭部讀數(shù)據(jù)。

 ?。ǘ┯忻艿?/p>

  有名管道也是半雙工的,不過它允許沒有親緣關系的進程間進行通信。具體點說就是,有名管道提供了一個路徑名與之進行關聯(lián),以FIFO(先進先出)的形式存在于文件系統(tǒng)中。這樣即使是不相干的進程也可以通過FIFO相互通信,只要他們能訪問已經(jīng)提供的路徑。

  值得注意的是,只有在管道有讀端時,往管道中寫數(shù)據(jù)才有意義。否則,向管道寫數(shù)據(jù)的進程會接收到內(nèi)核發(fā)出來的SIGPIPE信號;應用程序可以自定義該信號處理函數(shù),或者直接忽略該信號。

  二。信號量(semophore)

  信號量是一種計數(shù)器,可以控制進程間多個線程或者多個進程對資源的同步訪問,它常實現(xiàn)為一種鎖機制。實質上,信號量是一個被保護的變量,并且只能通過初始化和兩個標準的原子操作(P/V)來訪問。(P,V操作也常稱為wait(s),signal(s))

  三。信號(Signal)

  信號是Unix系統(tǒng)中使用的最古老的進程間通信的方法之一。操作系統(tǒng)通過信號來通知某一進程發(fā)生了某一種預定好的事件;接收到信號的進程可以選擇不同的方式處理該信號,一是可以采用默認處理機制—進程中斷或退出,一是忽略該信號,還有就是自定義該信號的處理函數(shù),執(zhí)行相應的動作。

  內(nèi)核為進程生產(chǎn)信號,來響應不同的事件,這些事件就是信號源。信號源可以是:異常,其他進程,終端的中斷(Ctrl-C,Ctrl+\等),作業(yè)的控制(前臺,后臺進程的管理等),分配額問題(cpu超時或文件過大等),內(nèi)核通知(例如I/O就緒等),報警(計時器)。

  四。消息隊列(Message Queue)

  消息隊列就是消息的一個鏈表,它允許一個或者多個進程向它寫消息,一個或多個進程向它讀消息。Linux維護了一個消息隊列向量表:msgque,來表示系統(tǒng)中所有的消息隊列。

  消息隊列克服了信號傳遞信息少,管道只能支持無格式字節(jié)流和緩沖區(qū)受限的缺點。

  五。共享內(nèi)存(shared memory)

  共享內(nèi)存映射為一段可以被其他進程訪問的內(nèi)存。該共享內(nèi)存由一個進程所創(chuàng)建,然后其他進程可以掛載到該共享內(nèi)存中。共享內(nèi)存是最快的IPC機制,但由于linux本身不能實現(xiàn)對其同步控制,需要用戶程序進行并發(fā)訪問控制,因此它一般結合了其他通信機制實現(xiàn)了進程間的通信,例如信號量。

  socket也是一種進程間的通信機制,不過它與其他通信方式主要的區(qū)別是:它可以實現(xiàn)不同主機間的進程通信。

進程間通信(IPC,Interprocess communication)是一組編程接口,讓程序員能夠協(xié)調(diào)不同的進程,使之能在一個操作系統(tǒng)里同時運行,并相互傳遞、交換信息。這使得一個程序能夠在同一時間里處理許多用戶的要求。因為即使只有一個用戶發(fā)出要求,也可能導致一個操作系統(tǒng)中多個進程的運行,進程之間必須互相通話。IPC接口就提供了這種可能性。每個IPC方法均有它自己的優(yōu)點和局限性,一般,對于單個程序而言使用所有的IPC方法是不常見的。

1、無名管道通信

無名管道(pipe):管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動,而且只能在具有親緣關系的進程間使用,進程的親緣關系通常是指父子進程關系。

2、高級管道通信

高級管道(popen):將另一個程序當做一個新的進程在當前程序進程中啟動,則它算是當前程序的子進程,這種方式我們稱為高級管道方式。

3、有名管道通信

有名管道(named pipe):有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。

4、消息隊列通信

消息隊列(message

queue):消息隊列是由消息的鏈表,存放在內(nèi)核中并由消息隊列標識符標識,消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。

5、信號量通信

信號量(semophore):信號量是一個計數(shù)器,可以用來控制多個進程對共享資源的訪問,它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程訪問該資源。因此,主要作為進程間以及同一進程內(nèi)不同線程之間的同步手段。

6、信號

信號(sinal):信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經(jīng)發(fā)生。

7、共享內(nèi)存通信

共享內(nèi)存(shared

memory):共享內(nèi)存就是映射一段能被其他進程所訪問的內(nèi)存,這段共享內(nèi)存由一個進程創(chuàng)建,但多個進程都可以訪問。共享內(nèi)存是最快的IPC方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現(xiàn)進程間的同步和通信。

8、套接字通信

套接字(socket):套接字也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同機器間的進程通信。

LINUX下系統(tǒng)編程,多進程間數(shù)據(jù)共享,即共享變量

There are programming details at this site:

Unix多進程編程和進程間的通訊

有詳細的源程序,我就不一一復制。

linux 可以照貓畫虎。

共享內(nèi)存相關的API怎么使用不難:

1. 首先調(diào)用shmget分配一個新的共享內(nèi)存,這里你可以指定其大小,如果你要分配一個整形,那你可以將size參數(shù)設置成4,如果你要共享一個結構體那就將size參數(shù)設置成你的結構體大小,操作系統(tǒng)不關心你要共享什么,它只關心你要分配多少個字節(jié)的區(qū)間。而且實際上操作系統(tǒng)會將你要求的大小按照內(nèi)存頁面的大小進行對齊,也就是說它可能實際上給你分配若干個頁面的物理存儲空間,只要這個空間能夠容納你所指定的大小就ok了。它的第三個參數(shù)是關于一些訪問權限設置的,要講起來太長,建議自己搜索一下,或者用man查查幫助。總之,調(diào)用完shmget以后系統(tǒng)會給你創(chuàng)建一段共享內(nèi)存,然后返回給你一個shmid,也就是這個共享內(nèi)存的標識,你可以理解為給它取了個名字。

2. 接著調(diào)用shmat將這段共享內(nèi)存映射到你的進程的虛擬地址空間上。這個函數(shù)的之一個參數(shù)就是你之前調(diào)用shmget創(chuàng)建的共享內(nèi)存的名字shmid;第二個參數(shù)是個指針,指向你的進程虛存空間中的某個地址,你可以通過傳入一個確定的地址強行要求操作系統(tǒng)將共享內(nèi)存映射到你指定的虛存地址上(可能會失敗,如果你指定的虛擬地址空間已經(jīng)映射了別的物理存儲空間),也可以通過傳入0地址讓系統(tǒng)給你選擇一個合適的地址(它會通過返回值把地址返回給你)。第三個參數(shù)則允許你指定一些特殊的標志位,還是那句話,太復雜自己搜索一下看看,一般應用不需要用到。

至于例子嘛你可以看看下面這個鏈接:

另外,你要知道只用共享內(nèi)存是不互斥的,你必須結合信號量一起使用才能防止互斥問題的出現(xiàn)。如果你共享的只是一個整形變量可能問題不大,因為對頁面對齊的整形變量的讀寫都是原子操作,但如果你共享的是個復雜的結構體就得小心了。

簡單的實現(xiàn),沒有添加同步機制,回頭再添加上去,而且,我是在不同終端里面寫的,你可以把兩段代碼,一個放到父進程,一個放到子進程…就可以了

你說的這些API,自己man 一次,看看說明就知道用法了….

樓上說的對齊的問題,我沒有太注意..不過,不管你要共享什么,一個sizeof看看大小,一個memcpy拷貝,你就作為數(shù)據(jù)直接拷貝到共享內(nèi)存區(qū)域就OK了…另外一邊再拷貝回來,用一個結構體類型的指針指向你拷貝回來的數(shù)據(jù),不就給這部分內(nèi)存再規(guī)劃成一個結構體了。。

至于具體的, KEY 的含義,你需要了解linux的ipc機制。

#include

#include

#include

#include

#define BUF_SIZE 100

#define KEY 99

int main(void)

{

int shmid;

char *shmptr;

shmid=shmget(99,BUF_SIZE,IPC_CREAT|0666);

if(shmid==-1)

{

printf(“Shared Memory Created error…\n”);exit(0);

}

shmptr=shmat(shmid,NULL,0);

if(shmptr==(void*)-1)

{

printf(“shmat error,shmptr= %d \n”,shmptr);

exit(1);

}

while(1)

{

printf(“type strings into Shared Memory:”);

fgets(shmptr,BUF_SIZE,stdin);

}

return 0;

}

下面這段就每隔10秒鐘掃描共享內(nèi)存區(qū)域的內(nèi)容:

#include

#include

#include

#include

#define BUF_SIZE 100

#define KEY 99

int main(void)

{

int shmid;

char *shmptr;

shmid=shmget(99,BUF_SIZE,IPC_CREAT|0666);

if(shmid==-1)

{

printf(“Shared Memory Created error…\n”);exit(0);

}

shmptr=shmat(shmid,NULL,0);

if(shmptr==(void*)-1)

{

printf(“shmat error,shmptr= %d \n”,shmptr);

exit(1);

}

while(1)

{

printf(“Infomation in Shared Memory:”);

printf(“%s \n”,shmptr);

sleep(10);

}

return 0;

}

幫你頂,希望有這方面專業(yè)知道的朋友能站出來幫助你解決困難.

關于linux不同進程信號燈共享的介紹到此就結束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。

香港服務器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務提供商,擁有超過10年的服務器租用、服務器托管、云服務器、虛擬主機、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗。專業(yè)提供云主機、虛擬主機、域名注冊、VPS主機、云服務器、香港云服務器、免備案服務器等。


分享文章:Linux進程間共享信號量的實現(xiàn)(linux不同進程信號燈共享)
網(wǎng)頁鏈接:http://m.5511xx.com/article/djsghsj.html