C语言中的共享内存问题

C语言中的共享内存问题,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

我只是重新发布了我之前的问题。我只是尽可能地压缩代码,其功能与主项目相同

共享内存。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_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