进程间通信2

本文档描述了一个使用共享内存实现的本地聊天应用中遇到的问题及解决方案。服务端在初始化过程中出现段错误,原因在于shmat()函数参数错误。客户端发送消息后,服务端未能正确显示,问题出在条件变量的初始化和信号发送的顺序。修正后的代码确保了锁的正确使用,避免了信息错乱。
摘要由CSDN通过智能技术生成

设计一个本机聊天功能
利用共享内存

#ifndef _CHAT_H
#define _CHAT_H
struct Msg {
    char name[20];
    char msg[1024];
    pthread_mutex_t mutex;
    pthread_cond_t cond;
};


#endif
#include "head.h"
#include "chat.h"

struct Msg *share_memory = NULL;

int main() {
    int shmid;
    key_t key = ftok(".", 202110);
    if ((shmid = shmget(key, sizeof(struct Msg), IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    if ((share_memory = (struct Msg*)shmat(shmid, NULL, 0)) < 0) {
        perror("shmat");
        exit(1);
    }
    // 设置锁的属性,让这个锁可以在进程中使用
    memset(share_memory, 0, sizeof(struct Msg));
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setpshared(&attr, 1);
    printf("1\n");
    pthread_mutex_init(&share_memory->mutex, &attr);
    printf("2\n");
    // 设置条件变量属性
    pthread_condattr_t c_attr;
    pthread_condattr_init(&c_attr);
    pthread_condattr_setpshared(&c_attr, 1);
    pthread_cond_init(&share_memory->cond, &c_attr);
    perror("pthread_cond_init");
    printf("123\n");
    // 初始化
    //pthread_cond_init(&share_memory->cond, &c_attr);
    printf("***\n");
    //pthread_mutex_init(&share_memory->mutex, &attr);
    printf("234\n");
    //memset(share_memory, 0, sizeof(struct Msg));

    printf("Server has ready!\n");
    while (1) {
        pthread_mutex_lock(&share_memory->mutex);
        printf("Server Get the mutex!\n");
        pthread_cond_wait(&share_memory->cond, &share_memory->mutex);
        printf("Server Wait the Signal\n");
        printf("<%s> : %s.\n", share_memory->name ,share_memory->msg);
        bzero(share_memory->msg, sizeof(share_memory->msg));
        pthread_mutex_unlock(&share_memory->mutex);
    }

    shmdt(share_memory);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}
#include "head.h"
#include "chat.h"

struct Msg *share_memory = NULL;

int main(int argc, char **argv) {
    key_t key;
    int opt, shmid;
    char name[20] = {0};
    while ((opt = getopt(argc, argv, "n:")) != -1) {
        switch (opt) {
            case 'n':
                strcpy(name, optarg);
            break;
            default:
            fprintf(stderr, "Usage : %s -n name\n", argv[0]);
        }
    }
    if ((key = ftok(".", 202110)) < 0) {
        perror("ftok");
        exit(1);
    }
    if ((shmid = shmget(key, sizeof(struct Msg), IPC_CREAT | 0666)) < 0) {
        perror("shmid");
        exit(1);
    }
    if ((share_memory = (struct Msg*)shmat(shmid, NULL, 0)) < 0) {
        perror("shmat");
        exit(1);
    }
    printf("name : %s\n", name);
    while (1) {
        char msg[1024] = {0};
        scanf("%[^\n]", msg);
        getchar();
        if (!strlen(msg)) continue;
        pthread_mutex_lock(&share_memory->mutex);
        strcpy(share_memory->name, name);
        strcpy(share_memory->msg, msg);
        pthread_cond_signal(&share_memory->cond);
        pthread_mutex_unlock(&share_memory->mutex);
        printf("Send the Signal\n");
        
    }
    shmdt(share_memory);
    return 0;
}

第一版本:
在写的时候遇到的问题:

  1. 在第一次运行服务端的时候,明明给权限加了0666 ,但是运行的时候还是出现段错误

问题在于shmat的时候,传值时,传入的是key 而不是shmid (nt 错误)

  1. 在运行客户端的时候,输入了内容,但是服务端没有显示

更nt 的错误,跳出的条件写反了

问题:

  1. 为啥在客户端先发信号再解锁?

首先担心的是发信号之后,服务端收到信号,但是加锁没有成功,但是因为在这里,加锁和发信号是临近的,所以发生率小
我们应该还考虑一点是如果先解锁,再发信号,有可能另外一个客户端抢了锁,导致信息错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值