2015-01-03 39 views
0

我的任務是使用程序創建共享內存。它將字符串從命令行參數寫入共享內存部分。它會被另一個程序讀取。我正在使用結構來創建共享內存。現在,我的問題是我無法將命令行中給出的字符串傳遞給結構變量。如何將多個字符串寫入一個char變量指針數組?如何使用指針數組將多個字符串存儲到結構中

#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <malloc.h> 
#include "shm-com.h" 

void main(int argc,char *argv[]) 
{ 
key_t shmKey; 
int shm_id,i,j=0; 
struct memory *dataptr; 
char *string[10]; 

shmKey = ftok(".",1234); 
printf("no. of strings %d\n",argc); 

shm_id = shmget(shmKey,sizeof(struct memory),0666 | IPC_CREAT); 

if(shm_id < 0) 
{ 
    perror("shm_id didn't create\n"); 
    exit(0); 
} 

dataptr = (struct memory *)shmat(shm_id,NULL,0); 
if((int) dataptr == -1) 
{ 
    perror("****didn't attatch to share memory\n"); 
} 

printf("share memory attatched at %p address\n",dataptr); 

dataptr->status = NOT_READY; 
for(i = 1;i < argc;i++) 
{ 
string[j] = argv[i]; 
j++; 
} 
printf("data attached to share memory\n"); 

for(i = 0;i < argc ; i++) 
{ 
printf("%s\n",string[i]); 
} 

for(i = 0;i < argc;i++) 
{ 
strcpy(dataptr->data[i],argv[i]); 

} 

dataptr->status = FILLED; 

printf("please start client window\n"); 

while(dataptr != TAKEN); 
sleep(1); 

shmdt((void *)dataptr); 
printf("server has detached sharre memory\n"); 

shmctl(shm_id,IPC_RMID,NULL); 

printf("server cancelled shared memroy\n"); 
exit(0); 
} 

和我的結構文件名SHM-com.h是

#define TAKEN 1 
#define FILLED 0 
#define NOT_READY -1 

struct memory 
{ 
char *data[10]; 
int status; 
}; 
+0

你可能笏使用某種共享的信號或自旋鎖,而不是簡單的「INT狀態」它有助於避免競爭條件和可能比檢查更efficint休眠循環。 – Jasen

回答

1

,你必須將蜇複製到共享內存中的緩衝區,因爲共享內存可以有不同的基礎地址在每個進程中,你將不得不引用它們通過偏移到緩衝區而不是通過指針。

然後,您還必須在緩衝區中保留已用/免費的地圖,以便知道哪些部分是空閒的以及使用哪些部分。共享內存有利於廣播數據,但是在兩個進程之間,通常更容易使用某種套接字(unix或inet)或管道(匿名或命名)。

0

主要問題是,你的結構只包含字符串指針,而不是實際的字符串內容(仍位於內存中屬於原工藝,共享內存)的事實。

最簡單的解決方案是使用二維字符數組。

struct memory 
{ 
    char data[10][100]; 
    int status; 
}; 

您已經使用strcpy將數據複製到結構,所以它沒有太多的代碼修改工作。雖然我強烈建議您用不易於出現buffer overflow的東西替換strcpy。缺點:如果字符串長度不同,那麼由於數組的固定大小,您的結構可能會包含大量未使用的空間。另一種方法是使用單個一維字符數組並簡單地連接十個字符串,使用\0作爲分隔符。

部分代碼(只是改變):

struct memory 
{ 
    int status; 
    char data[1];  /* data MUST be last in the struct! */ 
}; 

int size = sizeof(struct memory) - 1; /* subtract one because [1] will be overruled */ 
for (i = 1; i < argc; i++) 
{ 
    size += strlen(argv[i]) + 1;  /* adding one to hold '\0' */ 
} 

shm_id = shmget(shmKey, size, 0666 | IPC_CREAT); /* I adjusted the size parameter here */ 

int offset = 0; 
for (i = 1; i < argc; i++) 
{ 
    strcpy(dataptr->data + offset, argv[i]); 
    offset += strlen(argv[i]) + 1; 
} 

當然,你將不得不作出在接收端類似的變化;在每個'\ 0'字符處分割數據。


有點偏離主題,這段代碼是錯誤的:

所有的
while(dataptr != TAKEN); 
sleep(1); 

首先,你用一個整數比較指針(請讓編譯器警告)。就像現在這樣,它是一個無限循環。即使不是,它也是一個CPU密集型的busy-waiting循環。如果sleep(1);應該是循環的一部分(這肯定會讓CPU休息一下),那麼您應該刪除while語句末尾的分號。

我想你想做到這一點:

while (dataptr->status != TAKEN) 
    sleep(1); 
相關問題