C语言中的共享内存问题
我只是重新发布了我之前的问题。我只是尽可能地压缩代码,其功能与主项目相同 共享内存。she_demo.cC语言中的共享内存问题,c,posix,shared-memory,C,Posix,Shared Memory,我只是重新发布了我之前的问题。我只是尽可能地压缩代码,其功能与主项目相同 共享内存。she_demo.c #define DATA_LEN 10 char *key = "/shm1"; pthread_mutex_t mutex; void initalize(void){ pthread_mutex_init(&mutex, NULL); } void *reader(void* arg) { char pack[10]; pthread_mutex_lo
#define DATA_LEN 10
char *key = "/shm1";
pthread_mutex_t mutex;
void initalize(void){
pthread_mutex_init(&mutex, NULL);
}
void *reader(void* arg) {
char pack[10];
pthread_mutex_lock(&mutex);
int shm_fd = shm_open(key, O_CREAT | O_RDONLY , S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
printf("Could not open shared memory \n");
return (void*)-1;
}
void *shmp_rd = mmap(NULL, DATA_LEN, PROT_READ, MAP_SHARED, shm_fd, 0);
if(shmp_rd == MAP_FAILED){
printf("Mapping failed\n");
return (void*)-1;
}
memcpy(pack, shmp_rd, DATA_LEN);
if (munmap(shmp_rd, DATA_LEN) == -1) {
printf("Unmapping failed\n");
return (void*) NULL;
}
shm_unlink(key);
close(shm_fd);
pthread_mutex_unlock(&mutex);
return (void*)pack;
}
void *writer(void *arg) {
char pack[10];
strcpy(pack, (char*)arg);
printf("%s\n", pack);
pthread_mutex_lock(&mutex);
int shm_fd = shm_open(key, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
printf("Could not create shared memory\n");
return (void*)-1;
}
if (ftruncate(shm_fd, DATA_LEN) == -1) {
printf("Error on ftruncate to allocate \n");
return (void*)-1;
}
void *shmp_wr = mmap(NULL, DATA_LEN, PROT_WRITE, MAP_SHARED, shm_fd, 0);
if(shmp_wr == MAP_FAILED){
printf("Mapping failed\n");
return (void*)-1;
}
memcpy(shmp_wr, pack, strlen(pack));
if (munmap(shmp_wr, DATA_LEN) == -1) {
printf("Unmapping failed\n");
return (void*)-1;
}
pthread_mutex_unlock(&mutex);
close(shm_fd);
return (void*)1;
}
服务器.c
#define DATA_LEN 70
#define SOCKET_NAME "socket"
extern void *writer(void*);
extern void initalize(void);
int main(){
char *item[6] ={"Bruno", "Ben", "Zack", "Jack"};
pthread_t tid;
int connection_socket, data_socket, ret; //crete socket
struct sockaddr_un name;
unlink(SOCKET_NAME);
connection_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if(connection_socket == -1){
perror("socket");
return -1;
}
memset(&name, 0, sizeof(struct sockaddr_un));
name.sun_family = AF_UNIX;
strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);
ret = bind(connection_socket, (const struct sockaddr *) &name, sizeof(struct sockaddr_un));
if (ret == -1) {
perror("bind");
exit(1);
}
ret = listen(connection_socket, 20);
if (ret == -1) {
perror("listen");
exit(1);
}
data_socket = accept(connection_socket, NULL, NULL);
void* ret_vpr;
int i = 0;
char sync[5];
strcpy(sync, "ADD");
while(i < 4){
printf("%d:\n", i);
write(data_socket, sync, strlen(sync));
pthread_create(&tid, NULL, writer, (void *)item[i]);
pthread_join(tid, &ret_vpr);
if((int)ret_vpr == 1){
}
i++;
}
close(data_socket);
close(connection_socket);
return 0;
}
#定义数据#70
#定义SOCKET\u名称“SOCKET”
外部无效*写入程序(无效*);
外部无效初始化(void);
int main(){
字符*项目[6]={“布鲁诺”、“本”、“扎克”、“杰克”};
pthread_t tid;
int-connection\u-socket,data\u-socket,ret;//crete-socket
结构sockaddr_un name;
取消链接(插座名称);
连接\u套接字=套接字(AF\u UNIX,SOCK\u流,0);
如果(连接插座==-1){
佩罗(“插座”);
返回-1;
}
memset(&name,0,sizeof(struct sockaddr_un));
name.sun_family=AF_UNIX;
strncpy(name.sun\u path,SOCKET\u name,sizeof(name.sun\u path)-1);
ret=bind(connection_socket,(const struct sockaddr*)和name,sizeof(struct sockaddr_un));
如果(ret==-1){
佩罗(“绑定”);
出口(1);
}
ret=监听(连接插座,20);
如果(ret==-1){
佩罗尔(“倾听”);
出口(1);
}
数据\u套接字=接受(连接\u套接字,NULL,NULL);
void*ret_vpr;
int i=0;
字符同步[5];
strcpy(同步,“添加”);
而(i<4){
printf(“%d:\n”,i);
写入(数据插槽、同步、strlen(同步));
pthread_创建(&tid,NULL,writer,(void*)项[i]);
pthread_join(tid和ret_vpr);
如果((int)ret_vpr==1){
}
i++;
}
关闭(数据插座);
关闭(连接插座);
返回0;
}
客户c
#define DATA_LEN 70
#define SOCKET_NAME "socket"
extern void *reader(void*);
int main(void){
pthread_t tid;
char *item[4];
void *ret_vpr;
struct sockaddr_un addr;// create socket
int data_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (data_socket == -1) {
perror("socket");
exit(1);
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
if (connect(data_socket, (const struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) {
fprintf(stderr, "The server is down.\n");
exit(1);
}
printf("connected\n"); // create socket
int rc = 1;
char ch[6];
while(rc){
rc = read(data_socket, ch, sizeof(ch));
if(rc < 0){
perror("read");
break;
}
ch[rc] = '\0';
printf("%s\n", ch);
if(!strcmp(ch, "ADD")){
pthread_create(&tid, NULL, reader, NULL);
pthread_join(tid, &ret_vpr);
printf("%s\n", (char *) ret_vpr);
}
}
close(data_socket);
return 0;
}
#定义数据#70
#定义SOCKET\u名称“SOCKET”
外部无效*读卡器(无效*);
内部主(空){
pthread_t tid;
字符*项目[4];
void*ret_vpr;
struct sockaddr\u un addr;//创建套接字
int data_socket=socket(AF_UNIX,SOCK_STREAM,0);
如果(数据_套接字==-1){
佩罗(“插座”);
出口(1);
}
memset(&addr,0,sizeof(struct sockaddr_un));
addr.sun_family=AF_UNIX;
strncpy(addr.sun\u路径、套接字名称、sizeof(addr.sun\u路径)-1);
if(connect(data_socket,(const struct sockaddr*)和addr,sizeof(struct sockaddr_un))=-1){
fprintf(stderr,“服务器已关闭。\n”);
出口(1);
}
printf(“已连接的\n”);//创建套接字
int rc=1;
char-ch[6];
while(rc){
rc=读取(数据_套接字,ch,sizeof(ch));
if(rc<0){
佩罗(“阅读”);
打破
}
ch[rc]='\0';
printf(“%s\n”,ch);
如果(!strcmp(ch,“ADD”)){
pthread_create(&tid,NULL,reader,NULL);
pthread_join(tid和ret_vpr);
printf(“%s\n”,(char*)ret_vpr);
}
}
关闭(数据插座);
返回0;
}
不可预知的seg故障发生在我运行项目时。首先,应该运行服务器,然后运行客户端。我认为问题出在客户端,当程序想要执行printf(“%s\n”,(char*)ret\u vpr) 我根本不想从您的代码中运行程序,但您的问题可能是接下来的两行顺序错误
pthread_cond_wait(&cnd, &mutex);
pthread_mutex_lock(&mutex);
一定是
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cnd, &mutex);
因此,读卡器没有很好地同步
在调用pthread\u cond\u wait之前,必须先获得互斥锁
[编辑]其他备注: 在Writer中,您可以执行以下操作:
char shm_data[70];
sprintf(shm_data, "%s -> %s", pack->data, pack->hash);
memcpy(shmp_wr, shm_data, strlen(shm_data));
首先,为什么是70而不是数据长度(+1),大小为32的读卡器也存在同样的问题
第二,您确定没有写出shm_数据和/或shmp_wr吗
最后,不复制字符串结尾的空字符,在读卡器中执行sscanf(shm_数据,“%s->%s”,数据,散列),该读卡器需要最后的空字符
而且做起来也很奇怪
int i = pthread_create(&tid, NULL, reader, NULL);
紧接着
i = pthread_join(tid, &ret_vpr);
只需在当前线程中执行该任务
[从上一版本编辑] 函数读取器返回本地变量包的地址,如果没有未定义的行为,该地址将无法从函数中取消引用。但是你用它来 将包分配到堆中,而不是将其放置在读卡器中的堆栈中。当然,在错误情况下,在调用main中的printf之前,返回实例NULL并检查ret_vpr不为NULL 在这些更改之后,服务器和客户端的执行是:
$ ./server
0:
Bruno
1:
Ben
2:
Zack
3:
Jack
$ ./client
connected
ADD
Jack
ADD
Bruno
ADD
Ben
ADD
Zack
没用。在第一个程序中,只有链表的第一个节点被写入共享内存,第二个程序可以读取它。其他应该写入共享内存的节点不会被写入。Writer函数抛出“无法创建共享内存”。@BenEslami无论如何,行的顺序是错误的,您必须修复它。为什么你以前没有提到那个错误,你希望我们能猜出你没说什么吗?修改程序以写入errno的值。如果要知道错误原因,还可以在“printf(“无法创建共享内存”);行下方的write函数中使用strerror etcI put perror(“错误”)。结果是“无效参数”@BenEslami我让你给errno值(可能是perror),有几种可能出现“无效参数”。key的值是多少?errno:22的值如果在创建后立即使用联接序列化线程,为什么要使用线程?在任何情况下,让我请你们把这个大幅削减到最低限度。也许启动一个将pid写入共享内存的“服务器”进程,然后启动一个手动调用的“客户端”进程,在服务器仍在运行时读取pid。然后可能会添加套接字IPC来协调它。然后,如果您认为这会增加一些内容,那么可以添加线程。如果你这样做,我怀疑你会发现你的问题。@pilcrow-我使用线程,因为我必须通过增加线程数来测试整个程序的吞吐量。-该系统的体系结构如下:服务器启动,管理员可以向其本地表添加一些数据。一段时间后,另一个进程连接到服务器以将其表与服务器的表同步。该表通过共享内存共享,服务器中对其相应表的任何操作都将被通知
$ ./server
0:
Bruno
1:
Ben
2:
Zack
3:
Jack
$ ./client
connected
ADD
Jack
ADD
Bruno
ADD
Ben
ADD
Zack