2013-05-19 30 views
1

我試圖寫入共享內存,但由於某種原因,我調用shmat()和strcpy後,我得到分段錯誤(核心轉儲)爲什麼?shmat返回分段錯誤(核心轉儲)

這是我的代碼:

int fd,shmid; 
key_t shmkey; 
char *shm_add; 
pid_t pid,pid1=0,pid2=0; 

shmkey=ftok("shmdemo.c",'j'); 
if (shmkey == (key_t)-1) 
{ 
    printf("main: ftok() for shm failed\n"); 
    return -1; 
} 
shmid=shmget(shmkey, 50, 0666 | IPC_CREAT | IPC_EXCL); 
if (shmid == -1) 
{ 
    printf("main: shmget() failed\n"); 
    return -1; 
} 
shm_add=(char *)shmat(shmid,0,0); 
if (shm_add==NULL) 
{ 
    printf("main: shmat() failed\n"); 
    return -1; 
} 

strcpy(shm_add,"hello"); 

編輯:我對目錄中的文件名shmdemo.c,和shmget的的錯誤號說「文件已存在」,但是當我從刪除「shmdemo.c」目錄中,一個新的errno出現在ftok中,表示「沒有這樣的文件或目錄」。

謝謝你,阿薩夫。

+1

'shm_add'的價值是什麼? (或者,一般來說,如果他們報告成功,請檢查所有系統調用的返回值。) – millimoose

+0

好吧,我爲syscalls添加了返回值,問題在於shmget。爲什麼? –

+2

那麼[通話失敗後'errno'的值是什麼](http://linux.die.net/man/3/perror)?因此,[man shmget'](http://linux.die.net/man/2/shmget)表示errno的值是什麼意思? – millimoose

回答

0

嘗試刪除IPC_EXCL標誌並檢查程序。

+0

那麼當我刪除它的工作!這有什麼重要的?我還需要在創建一個新的部分之前刪除該部分? –

+0

@asafregev如果沒有'IPC_EXCL',就會得到先前創建的共享內存段。但是請注意,它將具有它首次分配的大小,而不是當前'shmget'調用的大小,這就是爲什麼當你想要確保獲得新的內存段時使用IPC_EXCL的原因。 (這通常是您不希望顯式獲取先前創建的期望值的期望。) – millimoose

+1

使用IPC_EXCL意味着您可以保證沒有其他進程在使用共享內存密鑰;如果你不在'shmget()'調用中使用它,你可能會使用其他人的大塊共享內存,這通常會導致至少一個程序非常不快。因此,從長遠來看,IPC_EXCL參數對於安全性非常重要。在短期內,省略IPC_EXCL將使代碼超越駝峯,直到您在程序退出之前刪除共享內存段。 –

2

回答各種意見。當您撥打:

shmget(..., IPC_CREAT | IPC_EXCL); 

你與標誌說的話是:創建一個新的共享內存這個關鍵部分,確保沒有共享內存段與鍵已經存在。

如果你只使用:

shmget(..., IPC_CREAT); 

你說:如果一個共享內存段已與此鍵存在,返回它; 否則爲此密鑰創建一個新的並返回該密鑰。

通常,您可能不希望調用的第二個變體。沒有增加任何你自己的不確定性,併發是很難的。 (即讓一組協作進程中的任何一個首先創建共享內存,而不是指定「擁有者」進程)。

當使用第一個調用時,如果共享內存段已經存在於給定的鍵,系統調用失敗,並且errnoEEXISTS。 SysV IPC是持久的,所以它們不會在程序退出後自動清除,比如文件描述符。 (實際上,它們更類似於臨時文件。)

你應該在程序中使用類似shmctl(shmid, IPC_RMID, NULL);的東西來清理它們。您還可以使用ipcs檢查雜散IPC對象,並使用ipcrmcleanipcs刪除遺留的IPC對象。