⑴ c/c++ unix c/linux c 嵌入式 共享內存
錯誤比較不明顯,最要的錯誤是int shmid=shmget(key,4,IPC_CREAT|IPC_EXCL|0660);這一行之中的標志位IPC_EXCL確保創建新的唯一的共享內存,如果已經存在(也就是說之前使用了一次),他將返回錯誤,故將這個標志位去掉,其他的不是很嚴重,忽略的是沒有最後刪除共享內存,而只是分離了共享內存。修改代碼如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
intmain()
{
key_tkey=ftok(".",100);
if(key==-1){
perror("ftok");
return-1;
}
intshmid=shmget(key,0,0);
if(shmid==-1)
{
perror("shmget");
exit(-1);
}
void*p=shmat(shmid,0,0);
if(p==(void*)-1)
{perror("shmat");
exit(-1);
}
int*pi=p;
printf("*pi=%d ",*pi);
shmdt(p);
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
intmain()
{
key_tkey=ftok(".",100);
if(key==-1){
perror("ftok");
return-1;
}
intshmid=shmget(key,4,IPC_CREAT|0660);
if(shmid==-1)
{
perror("shmget");
exit(-1);
}
void*p=shmat(shmid,0,0);
if(p==(void*)-1)
{perror("shmat");
exit(-1);
}
int*pi=p;
*pi=100;
shmdt(p);
}
⑵ 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共享內存會不會被編譯器優化
利用共享內存(Share Memory)可以讓我們在任意兩個進程之間傳遞數據,而且也是相對容易實現的一種方法,在正常情
況下,一個進程所使用的內存是不允許其它進程訪問的,但是通過共享內存可以實現數據的共享。
使用共享內存用到的API函數有:
# include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
key_t ftok(const char *pathname, int proj_id)
其中pathname為當前進程的程序名,第二個參數為進程所開辟的第幾個共享內存,返回一個key_t值,用於共享內存的獲取
使用。
int shmget(key_t shmkey, int shmsiz, int flag)
void *shmat(int shmid, char *shmaddr, int shmflag)
int shmdt(char *shmaddr)
shmget是用來創建或者指向一塊共享內存的函數,其中shmkey是共享內存的標識符,如果父子關系的進程間通信的話,這
個標識用IPC_PRIVATE替代,如果沒有任何關系,可以使用ftok計算出來;Shmsiz是這塊內存的大小;flag是這塊內存的模
式和許可權標識(IPC_CREAT, IPC_ALLOC, IPC_EXCL,0666許可權)。函數成功返回共享內存的shmid,否則返回-1表示失敗。
Shmat用來允許進程訪問共享內存的函數,其中shmid是共享內存的ID,shmaddr是共享內存起始位置,shmflag是本進程對
內存操作模式,SHM_RDONLY是只讀模式,成功返回共享內存的起始位置。
Shmdt與shmat相反,是用來禁止進程訪問一塊共享內存的函數。
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
其中shmid是共享內存的ID,cmd是控制命令(IPC_STAT, IPC_SET, IPC_RMID),struct shmid_ds *buf是一個結構體指針
,如果要改變共享內存的狀態,使用它來指定,獲得狀態就存放在這個結構體中。
上述API函數的詳細說明請使用man(男人)查看:
# man shmget | shmat | shmdt | shmctl
下面使用一個簡單的例子說明如何使用共享內存。
// sharememcut.c 拷貝用戶輸入的字元串到共享內存中
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main()
{
key_t shmkey;
int shmid, in_tmp;
char *head, *pos, in_data[4096], *in_ptr;
// Create share memory KEY
shmkey = ftok("sharememcut", 1);
// Get the share memory ID
shmid = shmget(shmkey, sizeof(in_data), IPC_CREAT | 0666);
// Allow the process to access share memory, and get the address
head = pos = shmat(shmid, 0, 0);
in_ptr = in_data;
// Receive the character from stdin, 'q' to quit
while ((in_tmp = getchar()) != 'q') {
*in_ptr = in_tmp;
in_ptr++;
}
*in_ptr = '\0';
in_ptr = in_data;
// Cut the data into share memory
while (*in_ptr != '\0') {
*pos++ = *in_ptr++;
}
// Prohabit the process to access share memory
shmdt(head);
return 0;
}
# gcc -o sharememcut sharememcut.c 編譯sharememcut.c
# ./sharememcut 執行sharememcut創建共享內存
…
# ipcs -m | grep 4096 查看創建的共享內存
0x01068288 348848145 root 666 4096 0
// sharemempaste.c 將共享內存的內容顯示在屏幕上並且刪除共享內存
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main()
{
key_t shmkey;
int shmid;
char *head, *pos, out_data[4096], *out_ptr;
// Create share memory KEY
shmkey = ftok("sharememcut", 1);
// Get the share memory ID
shmid = shmget(shmkey, sizeof(out_data), 0666);
if (shmid == -1)
return -1;
// Allow the process to access share memory, and get the address
head = pos = shmat(shmid, 0, 0);
out_ptr = out_data;
// Get the data from share memory
while (*pos != '\0') {
*out_ptr++ = *pos++;
}
*out_ptr = '\0';
// Output the data into stdout
printf("%s\n", out_data);
fflush(stdout);
// Prohabit the process to access share memory
shmdt(head);
// Delete the share memory
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
# gcc -o sharemempaste sharemempaste.c 編譯sharemempaste.c
# ./sharemempaste 執行程序顯示共享內存的內容
⑷ linux命令怎麼刪除共享內存
可以使用samba協議。Samba是在Linux和UNIX系統上實現SMB協議的一個免費軟體,由伺服器及客戶端程序構成。SMB是一種在區域網上共享文件和列印機的一種通信協議,它為區域網內的不同計算機之間提供文件及列印機等資源的共享服務。
⑸ linux共享內存的控制釋放
調用 shmctl(Shared Memory Control,控制共享內存)函數會返回一個共享內存塊的相關信息。同時 shmctl 允許程序修改這些信息。該函數的第一個參數是一個共享內存塊標識。
要獲取一個共享內存塊的相關信息,則為該函數傳遞 IPC_STAT 作為第二個參數,同時傳遞一個指向一個 struct shmid_ds 對象的指針作為第三個參數。
要刪除一個共享內存塊,則應將 IPC_RMID 作為第二個參數,而將 NULL 作為第三個參數。當最後一個綁定該共享內存塊的進程與其脫離時,該共享內存塊將被刪除。
您應當在結束使用每個共享內存塊的時候都使用 shmctl 進行釋放,以防止超過系統所允許的共享內存塊的總數限制。調用 exit 和 exec 會使進程脫離共享內存塊,但不會刪除這個內存塊。 要查看其它有關共享內存塊的操作的描述,請參考shmctl函數的手冊頁。
⑹ linux 共享內存 地址是唯一的嗎
所謂共享內存就是使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。其他進程能把同一段共享內存段「連接到」他們自己的地址空間里去。所有進程都能訪問共享內存中的地址。如果一個進程向這段共享內存寫了數據,所做的改動會即時被有訪問同一段共享內存的其他進程看到。共享內存的使用大大降低了在大規模數據處理過程中內存的消耗,但是共享內存的使用中有很多的陷阱,一不注意就很容易導致程序崩潰。
超過共享內存的大小限制?
在一個linux伺服器上,共享內存的總體大小是有限制的,這個大小通過SHMMAX參數來定義(以位元組為單位),您可以通過執行以下命令來確定 SHMMAX 的值:
# cat /proc/sys/kernel/shmmax
如果機器上創建的共享內存的總共大小超出了這個限制,在程序中使用標准錯誤perror可能會出現以下的信息:
unable to attach to shared memory
解決方法:
1、設置 SHMMAX
SHMMAX 的默認值是 32MB 。一般使用下列方法之一種將 SHMMAX 參數設為 2GB :
通過直接更改 /proc 文件系統,你不需重新啟動機器就可以改變 SHMMAX 的默認設置。我使用的方法是將以下命令放入 />etc/rc.local 啟動文件中:
# echo "2147483648" > /proc/sys/kernel/shmmax
您還可以使用 sysctl 命令來更改 SHMMAX 的值:
# sysctl -w kernel.shmmax=2147483648
最後,通過將該內核參數插入到 /etc/sysctl.conf 啟動文件中,您可以使這種更改永久有效:
# echo "kernel.shmmax=2147483648" >> /etc/sysctl.conf
2、設置 SHMMNI
我們現在來看 SHMMNI 參數。這個內核參數用於設置系統范圍內共享內存段的最大數量。該參數的默認值是 4096 。這一數值已經足夠,通常不需要更改。
您可以通過執行以下命令來確定 SHMMNI 的值:
# cat /proc/sys/kernel/shmmni
4096
3、設置 SHMALL
最後,我們來看 SHMALL 共享內存內核參數。該參數控制著系統一次可以使用的共享內存總量(以頁為單位)。簡言之,該參數的值始終應該至少為:
ceil(SHMMAX/PAGE_SIZE)
SHMALL 的默認大小為 2097152 ,可以使用以下命令進行查詢:
# cat /proc/sys/kernel/shmall
2097152
SHMALL 的默認設置對於我們來說應該足夠使用。
注意: 在 i386 平台上 Red Hat Linux 的 頁面大小 為 4096 位元組。但是,您可以使用 bigpages ,它支持配置更大的內存頁面尺寸。
⑺ linux 進程通信
nt shmget(key_t key, size_t size, int shmflg);
key_t key
-----------------------------------------------
key標識共享內存的鍵值: 0/IPC_PRIVATE。 當key的取值為IPC_PRIVATE,則函數shmget()將創建一塊新的共享內存;如果key的取值為0,而參數shmflg中設置了IPC_PRIVATE這個標志,則同樣將創建一塊新的共享內存。
在IPC的通信模式下,不管是使用消息隊列還是共享內存,甚至是信號量,每個IPC的對象(object)都有唯一的名字,稱為「鍵」(key)。通過「鍵」,進程能夠識別所用的對象。「鍵」與IPC對象的關系就如同文件名稱之於文件,通過文件名,進程能夠讀寫文件內的數據,甚至多個進程能夠共用一個文件。而在IPC的通訊模式下,通過「鍵」的使用也使得一個IPC對象能為多個進程所共用。
Linux系統中的所有表示System V中IPC對象的數據結構都包括一個ipc_perm結構,其中包含有IPC對象的鍵值,該鍵用於查找System V中IPC對象的引用標識符。如果不使用「鍵」,進程將無法存取IPC對象,因為IPC對象並不存在於進程本身使用的內存中。
通常,都希望自己的程序能和其他的程序預先約定一個唯一的鍵值,但實際上並不是總可能的成行的,因為自己的程序無法為一塊共享內存選擇一個鍵值。因此,在此把key設為IPC_PRIVATE,這樣,操作系統將忽略鍵,建立一個新的共享內存,指定一個鍵值,然後返回這塊共享內存IPC標識符ID。而將這個新的共享內存的標識符ID告訴其他進程可以在建立共享內存後通過派生子進程,或寫入文件或管道來實現。
int size(單位位元組Byte)
-----------------------------------------------
size是要建立共享內存的長度。所有的內存分配操作都是以頁為單位的。所以如果一段進程只申請一塊只有一個位元組的內存,內存也會分配整整一頁(在i386機器中一頁的預設大小PACE_SIZE=4096位元組)這樣,新創建的共享內存的大小實際上是從size這個參數調整而來的頁面大小。即如果size為1至4096,則實際申請到的共享內存大小為4K(一頁);4097到8192,則實際申請到的共享內存大小為8K(兩頁),依此類推。
int shmflg
-----------------------------------------------
shmflg主要和一些標志有關。其中有效的包括IPC_CREAT和IPC_EXCL,它們的功能與open()的O_CREAT和O_EXCL相當。
IPC_CREAT 如果共享內存不存在,則創建一個共享內存,否則打開操作。
IPC_EXCL 只有在共享內存不存在的時候,新的共享內存才建立,否則就產生錯誤。
如果單獨使用IPC_CREAT,shmget()函數要麼返回一個已經存在的共享內存的操作符,要麼返回一個新建的共享內存的標識符。如果將IPC_CREAT和IPC_EXCL標志一起使用,shmget()將返回一個新建的共享內存的標識符;如果該共享內存已存在,或者返回-1。IPC_EXEL標志本身並沒有太大的意義,但是和IPC_CREAT標志一起使用可以用來保證所得的對象是新建的,而不是打開已有的對象。對於用戶的讀取和寫入許可指定SHM_R和SHM_W,(SHM_R>3)和(SHM_W>3)是一組讀取和寫入許可,而(SHM_R>6)和(SHM_W>6)是全局讀取和寫入許可。
返回值
-----------------------------------------------
成功返回共享內存的標識符;不成功返回-1,errno儲存錯誤原因。
EINVAL 參數size小於SHMMIN或大於SHMMAX。
EEXIST 預建立key所致的共享內存,但已經存在。
EIDRM 參數key所致的共享內存已經刪除。
ENOSPC 超過了系統允許建立的共享內存的最大值(SHMALL )。
ENOENT 參數key所指的共享內存不存在,參數shmflg也未設IPC_CREAT位。
EACCES 沒有許可權。
ENOMEM 核心內存不足。
⑻ 如何設置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
來刪除該共享內存