導航:首頁 > 操作系統 > linuxshmget

linuxshmget

發布時間:2022-10-03 19:02:54

linux共享內存使用的過程

Linux共享內存使用的過程?

一、什麼是共享內存
顧名思義,共享內存就是允許兩個不相關的進程訪問同一個邏輯內存。共享內存是在兩個正在運行的進程之間共享和傳遞數據的一種非常有效的方式。不同進程之間共享的內存通常安排為同一段物理內存。進程可以將同一段共享內存連接到它們自己的地址空間中,所有進程都可以訪問共享內存中的地址,就好像它們是由用C語言函數malloc分配的內存一樣。而如果某個進程向共享內存寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的任何其他進程。

特別提醒:共享內存並未提供同步機制,也就是說,在第一個進程結束對共享內存的寫操作之前,並無自動機制可以阻止第二個進程開始對它進行讀取。所以我們通常需要用其他的機制來同步對共享內存的訪問,例如前面說到的信號量。

二、共享內存的使用
與信號量一樣,在Linux中也提供了一組函數介面用於使用共享內存,而且使用共享共存的介面還與信號量的非常相似,而且比使用信號量的介面來得簡單。它們聲明在頭文件 sys/shm.h中。
1、shmget函數
該函數用來創建共享內存,它的原型為:
int shmget(key_t key, size_t size, int shmflg);
第一個參數,與信號量的semget函數一樣,程序需要提供一個參數key(非0整數),它有效地為共享內存段命名,shmget函數成功時返回一個與key相關的共享內存標識符(非負整數),用於後續的共享內存函數。調用失敗返回-1.

不相關的進程可以通過該函數的返回值訪問同一共享內存,它代表程序可能要使用的某個資源,程序對所有共享內存的訪問都是間接的,程序先通過調用shmget函數並提供一個鍵,再由系統生成一個相應的共享內存標識符(shmget函數的返回值),只有shmget函數才直接使用信號量鍵,所有其他的信號量函數使用由semget函數返回的信號量標識符。

第二個參數,size以位元組為單位指定需要共享的內存容量

第三個參數,shmflg是許可權標志,它的作用與open函數的mode參數一樣,如果要想在key標識的共享內存不存在時,創建它的話,可以與IPC_CREAT做或操作。共享內存的許可權標志與文件的讀寫許可權一樣,舉例來說,0644,它表示允許一個進程創建的共享內存被內存創建者所擁有的進程向共享內存讀取和寫入數據,同時其他用戶創建的進程只能讀取共享內存。

❷ linux共享內存的分配

進程通過調用shmget(Shared Memory GET,獲取共享內存)來分配一個共享內存塊。
該函數的第一個參數是一個用來標識共享內存塊的鍵值。彼此無關的進程可以通過指定同一個鍵以獲取對同一個共享內存塊的訪問。不幸的是,其它程序也可能挑選了同樣的特定值作為自己分配共享內存的鍵值,從而產生沖突。用特殊常量IPC_PRIVATE作為鍵值可以保證系統建立一個全新的共享內存塊。
該函數的第二個參數指定了所申請的內存塊的大小。因為這些內存塊是以頁面為單位進行分配的,實際分配的內存塊大小將被擴大到頁面大小的整數倍。
第三個參數是一組標志,通過特定常量的按位或操作來shmget。這些特定常量包括:
IPC_CREAT:這個標志表示應創建一個新的共享內存塊。通過指定這個標志,我們可以創建一個具有指定鍵值的新共享內存塊。
IPC_EXCL:這個標志只能與 IPC_CREAT 同時使用。當指定這個標志的時候,如果已有一個具有這個鍵值的共享內存塊存在,則shmget會調用失敗。也就是說,這個標志將使線程獲得一個「獨有」的共享內存塊。如果沒有指定這個標志而系統中存在一個具有相同鍵值的共享內存塊,shmget會返回這個已經建立的共享內存塊,而不是重新創建一個。
模式標志:這個值由9個位組成,分別表示屬主、屬組和其它用戶對該內存塊的訪問許可權。其中表示執行許可權的位將被忽略。指明訪問許可權的一個簡單辦法是利用<sys/stat.h>中指定,並且在手冊頁第二節stat條目中說明了的常量指定。例如,S_IRUSR和S_IWUSR分別指定了該內存塊屬主的讀寫許可權,而 S_IROTH和S_IWOTH則指定了其它用戶的讀寫許可權。 下面例子中shmget函數創建了一個新的共享內存塊(當shm_key已被佔用時則獲取對一個已經存在共享內存塊的訪問),且只有屬主對該內存塊具有讀寫許可權,其它用戶不可讀寫。
int segment_id = shmget (shm_key, getpagesize (), IPC_CREAT | S_IRUSR| S_IWUSR ); 如果調用成功,shmget將返回一個共享內存標識符。如果該共享內存塊已經存在,系統會檢查訪問許可權,同時會檢查該內存塊是否被標記為等待摧毀狀態。

❸ linux兩個進程間共享內存通信都需要調用shmget函數么

兩個進程都需要調用shmget函數,是根據key值來實現訪問同一個共享內存的。
函數原型:int shmget(key_t key, size_t size, int shmflg)
由於是兩個進程訪問,最好是做兩手准備:
1,先創建,若創建成功,可以直接使用。
2,若創建失敗--此時,很可能另一個進程已經創建成功了,就不能再創建了。此時,就改為只是獲取。
示例代碼如下:
int mid = shmget(key, size, IPC_CREAT | 0660);
if(mid < 0){
mid = shmget(key, 0, 0);
}

❹ linux中shmget()創建共享內存的鍵如何獲得,可以隨便設一個數字嗎

可以隨便設置一下
可以用
ipcs
命令查看你使用的IPC
包括
共享內存
進程信號量
以及
消息隊列
以及IPC的

❺ linux中shmget()創建共享內存的鍵如何獲得,可以隨便設一個數字嗎

可以隨便設一個數字的,程序設計有時候就用固定的數字會好一點。
不一定就要用ftok函數 ,ftok函數可以提供一個數字給你去創建共享內存,但你用不同目錄時這個值是不同的。
如果你是在IBM的AIX系統下,ftok函數是有問題的 ,不知的是不是 bug。
比如如果有兩個分區,a,b
把 a 掛到 /mnt下
把b掛到/media下
那麼
ftok("/mnt")和ftok("/media")結果是一樣的。

❻ linux下通過shmget創建的共享內存,是屬於用戶空間還是內核空間

屬於用戶空間. shmat後返回的地址空間屬於用戶空間, 不同進程可以將同一物理內存區域映射到各自的用戶空間中。該空間可以隨意讀寫。note: 一個小屁進程,在用戶態時,是沒有許可權操作內核空間的。

虛擬地址空間=用戶空間+內核空間。

❼ Linux進程間通信

linux下進程間通信的幾種主要手段簡介:

一般文件的I/O函數都可以用於管道,如close、read、write等等。

實例1:用於shell

管道可用於輸入輸出重定向,它將一個命令的輸出直接定向到另一個命令的輸入。比如,當在某個shell程序(Bourne shell或C shell等)鍵入who│wc -l後,相應shell程序將創建who以及wc兩個進程和這兩個進程間的管道。

實例二:用於具有親緣關系的進程間通信

管道的主要局限性正體現在它的特點上:

有名管道的創建

小結:

管道常用於兩個方面:(1)在shell中時常會用到管道(作為輸入輸入的重定向),在這種應用方式下,管道的創建對於用戶來說是透明的;(2)用於具有親緣關系的進程間通信,用戶自己創建管道,並完成讀寫操作。

FIFO可以說是管道的推廣,克服了管道無名字的限制,使得無親緣關系的進程同樣可以採用先進先出的通信機制進行通信。

管道和FIFO的數據是位元組流,應用程序之間必須事先確定特定的傳輸"協議",採用傳播具有特定意義的消息。

要靈活應用管道及FIFO,理解它們的讀寫規則是關鍵。

信號生命周期

信號是進程間通信機制中唯一的非同步通信機制,可以看作是非同步通知,通知接收信號的進程有哪些事情發生了。信號機制經過POSIX實時擴展後,功能更加強大,除了基本通知功能外,還可以傳遞附加信息。

可以從兩個不同的分類角度對信號進行分類:(1)可靠性方面:可靠信號與不可靠信號;(2)與時間的關繫上:實時信號與非實時信號。

(1) 可靠信號與不可靠信號

不可靠信號 :Linux下的不可靠信號問題主要指的是信號可能丟失。

可靠信號 :信號值位於SIGRTMIN和SIGRTMAX之間的信號都是可靠信號,可靠信號克服了信號可能丟失的問題。Linux在支持新版本的信號安裝函數sigation()以及信號發送函數sigqueue()的同時,仍然支持早期的signal()信號安裝函數,支持信號發送函數kill()。

對於目前linux的兩個信號安裝函數:signal()及sigaction()來說,它們都不能把SIGRTMIN以前的信號變成可靠信號(都不支持排隊,仍有可能丟失,仍然是不可靠信號),而且對SIGRTMIN以後的信號都支持排隊。這兩個函數的最大區別在於,經過sigaction安裝的信號都能傳遞信息給信號處理函數(對所有信號這一點都成立),而經過signal安裝的信號卻不能向信號處理函數傳遞信息。對於信號發送函數來說也是一樣的。

(2) 實時信號與非實時信號

前32種信號已經有了預定義值,每個信號有了確定的用途及含義,並且每種信號都有各自的預設動作。如按鍵盤的CTRL ^C時,會產生SIGINT信號,對該信號的默認反應就是進程終止。後32個信號表示實時信號,等同於前面闡述的可靠信號。這保證了發送的多個實時信號都被接收。實時信號是POSIX標準的一部分,可用於應用進程。非實時信號都不支持排隊,都是不可靠信號;實時信號都支持排隊,都是可靠信號。

發送信號的主要函數有:kill()、raise()、 sigqueue()、alarm()、setitimer()以及abort()。

調用成功返回 0;否則,返回 -1。

sigqueue()是比較新的發送信號系統調用,主要是針對實時信號提出的(當然也支持前32種),支持信號帶有參數,與函數sigaction()配合使用。

sigqueue的第一個參數是指定接收信號的進程ID,第二個參數確定即將發送的信號,第三個參數是一個聯合數據結構union sigval,指定了信號傳遞的參數,即通常所說的4位元組值。

sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個進程發送信號。sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個進程發送信號。

inux主要有兩個函數實現信號的安裝: signal() sigaction() 。其中signal()在可靠信號系統調用的基礎上實現, 是庫函數。它只有兩個參數,不支持信號傳遞信息,主要是用於前32種非實時信號的安裝;而sigaction()是較新的函數(由兩個系統調用實現:sys_signal以及sys_rt_sigaction),有三個參數,支持信號傳遞信息,主要用來與 sigqueue() 系統調用配合使用,當然,sigaction()同樣支持非實時信號的安裝。sigaction()優於signal()主要體現在支持信號帶有參數。

消息隊列就是一個消息的鏈表。可以把消息看作一個記錄,具有特定的格式以及特定的優先順序。對消息隊列有寫許可權的進程可以向中按照一定的規則添加新消息;對消息隊列有讀許可權的進程則可以從消息隊列中讀走消息。消息隊列是隨內核持續的

消息隊列的內核持續性要求每個消息隊列都在系統范圍內對應唯一的鍵值,所以,要獲得一個消息隊列的描述字,只需提供該消息隊列的鍵值即可;

消息隊列與管道以及有名管道相比,具有更大的靈活性,首先,它提供有格式位元組流,有利於減少開發人員的工作量;其次,消息具有類型,在實際應用中,可作為優先順序使用。這兩點是管道以及有名管道所不能比的。同樣,消息隊列可以在幾個進程間復用,而不管這幾個進程是否具有親緣關系,這一點與有名管道很相似;但消息隊列是隨內核持續的,與有名管道(隨進程持續)相比,生命力更強,應用空間更大。

信號燈與其他進程間通信方式不大相同,它主要提供對進程間共享資源訪問控制機制。相當於內存中的標志,進程可以根據它判定是否能夠訪問某些共享資源,同時,進程也可以修改該標志。除了用於訪問控制外,還可用於進程同步。信號燈有以下兩種類型:

int semop(int semid, struct sembuf *sops, unsigned nsops); semid是信號燈集ID,sops指向數組的每一個sembuf結構都刻畫一個在特定信號燈上的操作。

int semctl(int semid,int semnum,int cmd,union semun arg)
該系統調用實現對信號燈的各種控制操作,參數semid指定信號燈集,參數cmd指定具體的操作類型;參數semnum指定對哪個信號燈操作,只對幾個特殊的cmd操作有意義;arg用於設置或返回信號燈信息。

進程間需要共享的數據被放在一個叫做IPC共享內存區域的地方,所有需要訪問該共享區域的進程都要把該共享區域映射到本進程的地址空間中去。系統V共享內存通過shmget獲得或創建一個IPC共享內存區域,並返回相應的標識符。內核在保證shmget獲得或創建一個共享內存區,初始化該共享內存區相應的shmid_kernel結構注同時,還將在特殊文件系統shm中,創建並打開一個同名文件,並在內存中建立起該文件的相應dentry及inode結構,新打開的文件不屬於任何一個進程(任何進程都可以訪問該共享內存區)。所有這一切都是系統調用shmget完成的。

shmget()用來獲得共享內存區域的ID,如果不存在指定的共享區域就創建相應的區域。shmat()把共享內存區域映射到調用進程的地址空間中去,這樣,進程就可以方便地對共享區域進行訪問操作。shmdt()調用用來解除進程對共享內存區域的映射。shmctl實現對共享內存區域的控制操作。這里我們不對這些系統調用作具體的介紹,讀者可參考相應的手冊頁面,後面的範例中將給出它們的調用方法。

註:shmget的內部實現包含了許多重要的系統V共享內存機制;shmat在把共享內存區域映射到進程空間時,並不真正改變進程的頁表。當進程第一次訪問內存映射區域訪問時,會因為沒有物理頁表的分配而導致一個缺頁異常,然後內核再根據相應的存儲管理機制為共享內存映射區域分配相應的頁表。

❽ linux下多次使用shmget函數(其第一個參數都是相同的),導致內存泄漏的問題!

肯定會再創建啊。你多次調用了shmget函數。。一般只需要創建一個共享內存就行了啊。。為什麼會調用很多次?應用有特殊要求?

❾ 如何設置linux的共享內存

首先先使用shmget建立一塊共享內存,然後向該內存中寫入數據並返回該共享內存shmid
使用另一個程序通過上一程序返回的shmid讀該共享內存內的數據
建立共享內存並寫入數據的程序

#include<stdio.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<errno.h>
voidget_buf(char*buf)
{
inti=0;
while((buf[i]=getchar())!=' '&&i<1024)
i++;
}
intmain(void)
{
intshmid;
shmid=shmget(IPC_PRIVATE,sizeof(char)*1024,IPC_CREAT|0666);
if(shmid==-1)
{
perror("shmget");
}
char*buf;
if((int)(buf=shmat(shmid,NULL,0))==-1)
{
perror("shmat");
exit(1);
}
get_buf(buf);
printf("%d ",shmid);
return0;
}
讀取數據的程序
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>
intmain(intargc,char**argv)
{
intshmid;
shmid=atoi(argv[1]);
char*buf;
if((int)(buf=shmat(shmid,NULL,0))==-1)
{
perror("shmat");
exit(1);
}
printf("%s ",buf);
shmdt(buf);
return0;
}

命令行的第一個參數設為第一個程序輸出的數字

使用完以後可以使用
ipcrm -m 19562507
來刪除該共享內存

閱讀全文

與linuxshmget相關的資料

熱點內容
戴爾塔式伺服器怎麼打開獨立顯卡 瀏覽:805
醫療程序員招聘 瀏覽:595
住宿app可砍價是什麼意思 瀏覽:133
java跳出語句 瀏覽:55
javastring個數 瀏覽:928
人工免疫演算法應用 瀏覽:79
有什麼app能收聽俄羅斯廣播電台 瀏覽:34
2015考研紅寶書pdf 瀏覽:443
程序員幾月跳槽合適 瀏覽:443
液壓油可壓縮嗎 瀏覽:944
源泉cad加密文件 瀏覽:127
銀河v10驅動重編譯 瀏覽:891
電腦上文件夾右擊就會崩潰 瀏覽:691
右美維持演算法 瀏覽:938
php基礎編程教程pdf 瀏覽:220
穿越之命令與征服將軍 瀏覽:351
android廣播重復 瀏覽:833
像阿里雲一樣的伺服器 瀏覽:319
水冷空調有壓縮機嗎 瀏覽:479
訪問日本伺服器可以做什麼 瀏覽:434