當前位置:首頁 » 操作系統 » linux信號量共享內存

linux信號量共享內存

發布時間: 2023-05-19 05:25:09

『壹』 linux查看共享內存命令

共享內存查看
使用ipcs命令,不加如何參數時,會把共享內存、信號量、消息隊列的信息都列印出來,如果只想顯示共享內存信息,使用如下命令:
[root@localhost ~]# ipcs -m

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 1867776 root 600 393216 2 dest
0x00000000 1900545 root 600 393216 2 dest
0x00030021 1703938 zc 666 131104 1
0x0003802e 1736707 zc 666 131104 1
0x00030004 1769476 zc 666 131104 1
0x00038002 1802245 zc 666 131104 1
0x00000000 1933318 root 600 393216 2 dest
0x00000000 1966087 root 600 393216 2 dest
0x00000000 1998856 root 600 393216 2 dest
0x00000000 2031625 root 600 393216 2 dest
0x00000000 2064394 root 600 393216 2 dest
0x0014350c 2261003 cs 666 33554432 2
0x00000000 2129932 root 600 393216 2 dest
0x00000000 2162701 root 600 393216 2 dest
0x00143511 395837454 root 666 1048576 1
其中:
第一列就是共享內存的key;
第二列是共享內存的編號shmid;
第三列就是創建的用戶owner;
第四列就是許可權perms;
第五列為創建的大小bytes;
第六列為連接到共享內存的進程數nattach;
第七列是共享內存的狀態status。其中顯示「dest」表示共享內存段已經被刪除,但是還有用戶在使用它,當該段內存的mode欄位設置為SHM_DEST時就會顯示「dest」。當用戶調用shmctl的IPC_RMID時,內存先查看多少個進程與這個內存關聯著,如果關聯數為0,就會銷毀這段共享內存,否者設置這段內存的mod的mode位為SHM_DEST,如果所有進程都不用則刪除這段共享內存。

『貳』 linux 共享內存 可不可以不加鎖呢 系統有兩個進程,一個負責寫入,一個負責讀取

能.並且是"要"加鎖.可以使用信號量加鎖.

『叄』 LINUX 信號量共存 共享內存通信

/***Msginput.c***/
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include"Mysem.h"

int main(){
FILE *fp;
int empty;
int full;
int mutex;
char * shm;
int shmid;
fp = fopen("shmid","r");
fread(&shmid,sizeof(int), 1, fp);
fread(&empty,sizeof(int), 1, fp);
fread(&full,sizeof(int), 1, fp);
fread(&mutex,sizeof(int), 1, fp);

fclose(fp);
shm = shmat(shmid, NULL, 0);

while(1){

P(&empty);
P(&mutex);

scanf("%s", shm);

if(strcmp(shm, "END") == 0){

V(&mutex);
V(&full);
break;
}

V(&mutex);
V(&full);

}
return 0;
}

/****Mysem.c*****/
#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

#include<sys/sem.h>

#include<unistd.h>

#include<stdio.h>

#include<errno.h>

#include<string.h>

#include "Mysem.h"

#define BUFFER_SIZE 512

int main(){

char *shm;

int empty;

int full;

int mutex;

int shmid;

int pid;

int i;

FILE *fp;

// int init_sem_value = 0;

empty = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));

if(empty == -1){

perror("semget");

exit(1);

}

if(semctl(empty, 0, SETVAL, 1)<0){

perror("semctl");

exit(1);

}

full = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));

if(full == -1){

perror("semget");

exit(1);

}

if(semctl(full, 0, SETVAL, 0)<0){

perror("semctl");

exit(1);

}

mutex = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));

if(mutex == -1){

perror("semget");

exit(1);

}

if(semctl(mutex, 0, SETVAL, 1)<0){

perror("semctl");

exit(1);

}

shmid = shmget(IPC_PRIVATE, (BUFFER_SIZE*sizeof(char)),(IPC_CREAT|0600));

if(shmid == -1){

perror("shmget");

exit(1);

}

shm = shmat(shmid, NULL, 0);

if(shm == (char*)-1){

perror("shmat");

exit(1);

}

fp = fopen("shmid","w");

fwrite(&shmid, sizeof(int), 1, fp);

fwrite(&empty, sizeof(int), 1, fp);

fwrite(&full, sizeof(int), 1, fp);

fwrite(&mutex, sizeof(int), 1, fp);

fclose(fp);

pid = fork();

if(pid == 0){

execlp("./Msginput", "./Msginput",0);

perror("execlp");

exit(1);

}else{

while(1){

P(&full);

P(&mutex);

printf("%s\n", shm);

if(strcmp(shm,"END") == 0){

V(&mutex);

V(&empty);

break;

}

V(&mutex);

V(&empty);

}

}

wait(0);

if(semctl(full, 0, IPC_RMID, 1) == -1){

perror("semctl");

exit(1);

}

if(semctl(empty, 0, IPC_RMID, 1) == -1){

perror("semctl");

exit(1);

}

if(semctl(mutex, 0, IPC_RMID, 1) == -1){

perror("semctl");

exit(1);

}

if(shmctl(shmid, IPC_RMID, NULL) == -1){

perror("shmctl");

exit(1);

}

exit(0);

}

/****Mysem.h*****/
void P(int *s);
void V(int *s);

extern void *shmat (int __shmid, __const void *__shmaddr, int __shmflg);

void P(int *s){
struct sembuf sembuffer, *sops;
sops=&sembuffer;
sops->sem_num = 0;
sops->sem_op = -1;
sops->sem_flg = 0;
if(semop(*s, sops, 1)<0){
perror("semop");
exit(1);
}
return ;
}
void V(int *s){
struct sembuf sembuffer, *sops;
sops = &sembuffer;
sops->sem_num = 0;
sops->sem_op = 1;
sops->sem_flg = 0;
if(semop(*s, sops, 1)<0){
perror("semop");
exit(1);
}
return;
}

『肆』 linux進程間通信問題 我想用共享內存的方式實現信號量控制一個不許並行的的函數 請問下面我的代碼合理嗎

看你好像完全搞混了。。。什麼叫用共享內存的方式實現信號量控制不能並行的代碼?
首先共享內存和信號量都可以實現進程間通信,但是他們的作用或者說使用的方向是有明顯的區別的:
1:共享內存是創建一塊內存區域,多個進程可以同時訪問該區域,一般用於進程間數據傳輸,效率比較明顯。
2:信號量則完全不同,信號量主要是用來控制臨界資源的訪問,也就是你說的不能並行的函數/代碼。
3:說一下實現,共享內存直接用API就可以了,信號量一般會進行封裝,類似於對鏈表的操作進行一些簡單的函數封裝一樣,下面給出信號量的使用實例代碼,可以參考:
sem_ctl.c文件內容:
int init_sem(int sem_id,int init_value)
{
union semun sem_union;
sem_union.val = init_value;

if(semctl(sem_id,0,SETVAL,sem_union) == -1)
{
perror("semctl");
return -1;
}
return 0;
}

int del_sem(int sem_id)
{
union semun sem_union;

if(semctl(sem_id,0,IPC_RMID,sem_union) == -1)
{
perror("delete semaphore");
return -1;
}
return 0;
}

int sem_p(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;

if(semop(sem_id,&sem_b,1) ==-1)
{
perror("P operation");
return -1;
}
return 0;
}

int sem_v(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;

if(semop(sem_id,&sem_b,1) == -1)
{
perror("V opration");
return -1;
}
return 0;
}

sem_ctl.h文件內容:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define MAX 128

int count; //全局變數,即臨界資源
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};

int init_sem(int sem_id,int init_value);
int del_sem(int sem_id);
int sem_p(int sem_id);
int sem_v(int sem_id);

在應用程序中只要包含sem_ctl.h就可以使用信號量的p、v操作了,下面給出2個c程序同時操作該信號量的情況,類似於:
server.c文件內容如下:
#include "util.h"
#include <signal.h>

int semid;
void sighandler(int signo)
{
del_sem(semid);
exit(0);
}
void server()
{
key_t key;

initcount();

if((key = ftok(".",'e')) == -1)
{
perror("ftok");
exit(1);
}
if((semid = semget(key,1,0666|IPC_CREAT|IPC_EXCL)) == -1)
{
perror("semget");
exit(1);
}
printf("the semid is :%d\n",semid);

init_sem(semid, 0);
signal(SIGINT,sighandler);
signal(SIGUSR1,sighandler);
signal(SIGALRM,sighandler);
while(1)
{
sem_p(semid);
/* do something */
printf("count =%d\n",count++);
sem_v(semid);
sleep(2);
}
}

int main(void)
{
server();
}
client.c文件內容如下:
#include "sem_ctl.h"

void custom()
{
int semid;
key_t key;

if((key = ftok(".",'e')) == -1)
{
perror("ftok");
exit(1);
}
if((semid = semget(key,0,0)) == -1)
{
perror("semget");
exit(1);
}
printf("the semid is :%d\n",semid);

while(1)
{
sem_p(semid); //獲得信號量,同一時間只有一個進程能獲得該信號量
/* do something */
printf("count =%d\n",count++);
sem_v(semid); //釋放信號量
sleep(2);
}

}

int main(void)
{
custom();
}

編譯好,運行的時候先運行server再運行client。

『伍』 linux|進程間通信如何加鎖

進程間通信有一種[共享內存]方式,大家有沒有想過,這種通信方式中如何解決數據競爭問題?我們可能自然而然的就會想到用鎖。但我們平時使用的鎖都是用於解決線程間數據競爭問題,貌似沒有看到過它用在進程中,那怎麼辦?

關於進程間的通信方式估計大多數人都知道,這也是常見的面試八股文之一。

個人認為這種面試題沒什麼意義,無非就是答幾個關鍵詞而已,更深入的可能面試官和面試者都不太了解。

關於進程間通信方式我之前在【這篇文章】中有過介紹,感興趣的可以移步去看哈。

進程間通信有一種[共享內存]方式,大家有沒有想過,這種通信方式中如何解決數據競爭問題?

我們可能自然而然的就會想到用鎖。但我們平時使用的鎖都是用於解決線程間數據競爭問題,貌似沒有看到過它用在進程中,那怎麼辦?

我找到了兩種方法,信號量和互斥鎖。

直接給大家貼代碼吧,首先是信號量方式:

代碼中的MEOW_DEFER,它內部的函數會在生命周期結束後觸發。它的核心函數其實就是下面這四個:

具體含義大家應該看名字就知道,這里的重點就是sem_init中的pshared參數,該參數為1表示可在進程間共享,為0表示只在進程內部共享。

第二種方式是使用鎖,即pthread_mutex_t,可是pthread_mutex不是用作線程間數據競爭的嗎,怎麼能用在進程間呢?

可以給它配置一個屬性,示例代碼如下:

它的默認屬性是進程內私有,但是如果給它配置成PTHREAD_PROCESS_SHARED,它就可以用在進程間通信中。

相關視頻推薦

360度無死角講解進程管理,調度器的5種實現

Linux進程間通信-信號量、消息隊列和共享內存

學習地址:C/C++Linux伺服器開發/後台架構師【零聲教育】-學習視頻教程-騰訊課堂

需要C/C++ Linux伺服器架構師學習資料加qun812855908獲取(資料包括 C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg 等),免費分享

完整代碼如下:

我想這兩種方式應該可以滿足我們日常開發過程中的大多數需求。

鎖的方式介紹完之後,可能很多朋友自然就會想到原子變數,這塊我也搜索了一下。但是也不太確定C++標准中的atomic是否在進程間通信中有作用,不過看樣子boost中的atomic是可以用在進程間通信中的。

其實在研究這個問題的過程中,還找到了一些很多解決辦法,包括:

Disabling Interrupts

Lock Variables

Strict Alternation

Peterson's Solution

The TSL Instruction

Sleep and Wakeup

Semaphores

Mutexes

Monitors

Message Passing

Barriers

這里就不過多介紹啦,大家感興趣的可以自行查閱資料哈。

『陸』 Linux進程通信實驗(共享內存通信,接上篇)

這一篇記錄一下共享內存實驗,需要linux的共享內存機制有一定的了解,同時也需要了解POSIX信號量來實現進程間的同步。可以參考以下兩篇博客: https://blog.csdn.net/sicofield/article/details/10897091
https://blog.csdn.net/ljianhui/article/details/10253345

實驗要求:編寫sender和receiver程序,sender創建一個共享內存並等待用戶輸入,然後把輸入通過共享內存發送給receiver並等待,receiver收到後把消息顯示在屏幕上並用同樣方式向sender發送一個over,然後兩個程序結束運行。
這個實驗的難點主要在於共享內存的創建和撤銷(涉及到的步驟比較多,需要理解各步驟的功能),以及實現兩個進程間的相互等待(使用信號量來實現,這里使用了有名信號量)

實驗心得:學習理解了linux的共享內存機制以及POSIX信號量機制。
兩個實驗雖然加強了對linux一些機制的理解,但是感覺對linux的學習還不夠,需要繼續學習。

『柒』 Linux信號量

信號量是包含一個非負整數型的變數,並且帶有兩個原子操作wait和signal。Wait還可以被稱為down、P或lock,signal還可以被稱為up、V、unlock或post。在UNIX的API中(POSIX標准)用的是wait和post。

對於wait操作,如果信號量的非負整形變數S大於0,wait就將其減1,如果S等於0,wait就將調用線程阻塞;對於post操作,如果有線程在信號量上阻塞(此時S等於0),post就會解除對某個等待線程的阻塞,使其從wait中返回,如果沒有線程阻塞在信號量上,post就將S加1.

由此可見,S可以被理解為一種資源的數量,信號量即是通過控制這種資源的分配來實現互斥和同步的。如果把S設為1,那麼信號量即可使多線程並發運行。另外,信號量不僅允許使用者申請和釋放資源,而且還允許使用者創造資源,這就賦予了信號量實現同步的功能。可見信號量的功能要比互斥量豐富許多。

POSIX信號量是一個sem_t類型的變數,但POSIX有兩種信號量的實現機制: 無名信號量 命名信號量 。無名信號量只可以在共享內存的情況下,比如實現進程中各個線程之間的互斥和同步,因此無名信號量也被稱作基於內存的信號量;命名信號量通常用於不共享內存的情況下,比如進程間通信。

同時,在創建信號量時,根據信號量取值的不同,POSIX信號量還可以分為:

下面是POSIX信號量函數介面:

信號量的函數都以sem_開頭,線程中使用的基本信號函數有4個,他們都聲明在頭文件semaphore.h中,該頭文件定義了用於信號量操作的sem_t類型:

【sem_init函數】:

該函數用於創建信號量,原型如下:

該函數初始化由sem指向的信號對象,設置它的共享選項,並給它一個初始的整數值。pshared控制信號量的類型,如果其值為0,就表示信號量是當前進程的局部信號量,否則信號量就可以在多個進程間共享,value為sem的初始值。

該函數調用成功返回0,失敗返回-1。

【sem_destroy函數】:

該函數用於對用完的信號量進行清理,其原型如下:

成功返回0,失敗返回-1。

【sem_wait函數】:

該函數用於以原子操作的方式將信號量的值減1。原子操作就是,如果兩個線程企圖同時給一個信號量加1或減1,它們之間不會互相干擾。其原型如下:

sem指向的對象是sem_init調用初始化的信號量。調用成功返回0,失敗返回-1。

sem_trywait()則是sem_wait()的非阻塞版本,當條件不滿足時(信號量為0時),該函數直接返回EAGAIN錯誤而不會阻塞等待。

sem_timedwait()功能與sem_wait()類似,只是在指定的abs_timeout時間內等待,超過時間則直接返回ETIMEDOUT錯誤。

【sem_post函數】:

該函數用於以原子操作的方式將信號量的值加1,其原型如下:

與sem_wait一樣,sem指向的對象是由sem_init調用初始化的信號量。調用成功時返回0,失敗返回-1。

【sem_getvalue函數】:

該函數返回當前信號量的值,通過restrict輸出參數返回。如果當前信號量已經上鎖(即同步對象不可用),那麼返回值為0,或為負數,其絕對值就是等待該信號量解鎖的線程數。

【實例1】:

【實例2】:

之所以稱為命名信號量,是因為它有一個名字、一個用戶ID、一個組ID和許可權。這些是提供給不共享內存的那些進程使用命名信號量的介面。命名信號量的名字是一個遵守路徑名構造規則的字元串。

【sem_open函數】:

該函數用於創建或打開一個命名信號量,其原型如下:

參數name是一個標識信號量的字元串。參數oflag用來確定是創建信號量還是連接已有的信號量。

oflag的參數可以為0,O_CREAT或O_EXCL:如果為0,表示打開一個已存在的信號量;如果為O_CREAT,表示如果信號量不存在就創建一個信號量,如果存在則打開被返回,此時mode和value都需要指定;如果為O_CREAT|O_EXCL,表示如果信號量存在則返回錯誤。

mode參數用於創建信號量時指定信號量的許可權位,和open函數一樣,包括:S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH、S_IWOTH。

value表示創建信號量時,信號量的初始值。

【sem_close函數】:

該函數用於關閉命名信號量:

單個程序可以用sem_close函數關閉命名信號量,但是這樣做並不能將信號量從系統中刪除,因為命名信號量在單個程序執行之外是具有持久性的。當進程調用_exit、exit、exec或從main返回時,進程打開的命名信號量同樣會被關閉。

【sem_unlink函數】:

sem_unlink函數用於在所有進程關閉了命名信號量之後,將信號量從系統中刪除:

【信號量操作函數】:

與無名信號量一樣,操作信號量的函數如下:

命名信號量是隨內核持續的。當命名信號量創建後,即使當前沒有進程打開某個信號量,它的值依然保持,直到內核重新自舉或調用sem_unlink()刪除該信號量。

無名信號量的持續性要根據信號量在內存中的位置確定:

很多時候信號量、互斥量和條件變數都可以在某種應用中使用,那這三者的差異有哪些呢?下面列出了這三者之間的差異:

『捌』 linux進程間信號量的分配釋放

和用於分配、釋放共享內存的 shmget 和 shmctl 類似,系統調用 semget 和 semctl 負責分配、釋放信號量。調用 semget 函數並傳遞如下參數:一個用於標識信號量組的鍵值,該組中包含的信號量數量和與 shmget 所需的相同的許可權位標識。該函數返回的是信號量組的標識符。您可以通過指定正確的鍵值來獲取一個已經存在的信號量的標識符;這種情況下,傳遞的信號量組的容量可以為0。
信號量會一直保存在系統中,甚至所有使用它們的進程都退出後也不會自動被銷毀。最後一個使用信號量的進程必須明確地刪除所使用的信號量組,來確保系統中不會有太多閑置的信號量組,從而導致無法創建新的信號量組。可以通過調用semctl來刪除信號量組。調用時的四個參數分別為信號量組的標識符,操作的信號量在組中的編號、常量IPC_RMID 和一個 union semun 類型的任意值(被忽略)。調用進程的有效用戶 id 必須與分配這個信號量組的用戶 id 相同(或者調用進程為 root 許可權亦可)。與共享內存不同,刪除一個信號量組會導致 Linux 立即釋放資源。
代碼 5.2 展示了用於分配和釋放一個二元信號量的函數。
代碼 5.2 (sem_all_deall.c)分配和釋放二元信號量
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h> /* 我們必須自己定義 semun 聯合類型。 */
union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; };
/* 獲取一個二元信號量的標識符。如果需要則創建這個信號量 */
int binary_semaphore_allocation (key_t key, int sem_flags)
{
return semget (key, 1, sem_flags);
} /* 釋放二元信號量。所有用戶必須已經結束使用這個信號量。如果失敗,返回 -1 */
int binary_semaphore_deallocate (int semid)
{
union semun ignored_argument; return semctl (semid, 1, IPC_RMID, ignored_argument);
}

『玖』 linux進程間通信 socket 共享內存 哪個快

進程間通訊進程間通信就是不同進程之間傳播或交換信息,進程的用戶空間是互相獨立的,進程之間可以利用系統空間交換信息。 管道(pipe)管道是一種半雙工的通信方式,數據只能單向流動。如果要進行雙工通信,需要建立兩個管道。 管道只能在具有親緣關系的進程間使用,例如父子進程或兄弟進程。 有名管道(named pipe) 有名管道也是雙半工的通信方式,但它允許無親緣關系的進程間使用。 信號量(semophore) 信號量常用來作為一種鎖機制來使用,它是一個記數器,用來控制多進程對共享資源的訪問,防止多個進程同時訪問一個共享資源。信號量主要用作為進程間或同一進程間不同線程之間的同步手段。 信號(sinal) 信號是一種比較復雜的通信方式,用於通知接收進程某些事件已經發生,要注意信號處理中調用的函數是否為信號安全。 消息隊列(message queue) 消息隊列是由消息的鏈表組成,存放在內核中並由消息隊列標識符標識。 共享內存(shared memory) 共享內存就是映射一段被其他進程所訪問的內存,這段共享內存由一個進程創建,可由多個進程訪問。共享內存是最快的IPC方式,它是針對其他進程間通信方式的低運行效率而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。 套接字(socket) 套接字也是進程間通信的一種方式,與其他方式不同的是,它可以用在不同主機間的進程通信(也是它的主要用途)。 幾種方式的缺點 管道: 速度慢,容量有限,只能用於親緣關系進程間通信。 有名管道: 同管道,不過允許無親緣關系進程間通信。 消息隊列: 容量受系統限制,隊列中會遺留數據,讀時要考慮到這些未讀完的數據。 信號量: 主要用於同步,無法傳遞復雜的數據信息。

『拾』 Linux 中有名信號量,異常關閉其他線程如何獲取

linux下進程間同步的機制有以下三種:
信號量
記錄鎖(文件鎖)
共享內存中的mutex
效率上 共享內存mutex > 信號量 > 記錄鎖
posix 提供了新的信號量 - 有名信號量,既可以使用在進程間同步也可以作為線程間同步的手段。效率比共享內存mutex要好一些

熱點內容
php開發的網頁 發布:2025-05-14 16:22:03 瀏覽:477
伺服器內存跑滿了怎麼回事 發布:2025-05-14 16:21:16 瀏覽:223
微信qq音樂緩存 發布:2025-05-14 16:16:16 瀏覽:468
c語言回收內存 發布:2025-05-14 16:16:08 瀏覽:143
2021國產安卓頂級旗艦買哪個 發布:2025-05-14 16:15:36 瀏覽:300
linux自學視頻 發布:2025-05-14 16:14:49 瀏覽:255
我的世界伺服器崩了重啟 發布:2025-05-14 16:09:37 瀏覽:44
android深拷貝 發布:2025-05-14 16:09:35 瀏覽:153
cf電腦版轉伺服器神器還在嗎 發布:2025-05-14 16:09:02 瀏覽:211
百度文庫伺服器如何搭建 發布:2025-05-14 16:09:00 瀏覽:248