C语言 进程通信-消息队列(MSG)

创建消息队列的的步骤:

1、获取key值ftok();

C语言 进程通信-消息队列(MSG)_第1张图片

    key_t key = ftok("/home", 123);
    if (key > 0)
    {
        perror("获取成功");
    }
    else
    {
        perror("获取失败");
    }

 注意:

C语言 进程通信-消息队列(MSG)_第2张图片

2、获取消息队列ID 

C语言 进程通信-消息队列(MSG)_第3张图片

C语言 进程通信-消息队列(MSG)_第4张图片

 此时消息队列已经在内核中创建完成了,接下来就可以发送消息了。同时也可以用命令查看消息队列的相关属性:

C语言 进程通信-消息队列(MSG)_第5张图片

 收发API

C语言 进程通信-消息队列(MSG)_第6张图片

 消息队列小例子:模拟的是飞秋的上下线通知以及消息的收发;

进程通信.c

#include "进程通信.h"
// 线程1发送消息
void *send_msg(void *arg)
{
    int op;

    while (1)
    {
        op = 2;
        memset(&buf, 0, sizeof(buf));
        printf("请选择操作\n");
        printf("1.发送信息\n");
        printf("2.退出\n");
        scanf("%d", &op);
        // while (getchar() != '\n')
        //     ;

        if (op == 1)
        {
            // printf("op1=%d\n", op);
            printf("请输入接收者的pid,和消息内容\n");
            scanf("%ld", &buf.mtype);
            // while (getchar() != '\n')
            //     ;
            scanf("%s", buf.data);
            // while (getchar() != '\n')
            //     ;
            int res = msgsnd(resource.msgque_id, &buf, strlen(buf.data), 0);
            if (res == 0)
            {

                perror(" msgsnd ok");
            }
            continue;
        }
        if (op == 2)
        {
            // printf("op2=%d\n", op);
            printf("break\n");
            break;
        }
        // printf("op3=%d\n", op);
    }
}

// 线程2接受消息
void *rcv_msg(void *arg)
{
    memset(&buf, 0, sizeof(buf));
    buf.mtype = resource.my_info.pid;
    while (1)
    {
        memset(buf.data, 0, sizeof(buf.data));
        int res = msgrcv(resource.msgque_id, &buf, sizeof(buf.data), buf.mtype, 0);
        printf("收到消息:%s\n", buf.data);
    }
}

// 资源准备,打开文件目录,消息队列以及,共享内存等
int Prepare_for()
{
    // 创建消息队列----------------
    // 消息队列创建key
    key_t msgque_key = ftok("/home", 123);
    if (msgque_key < 0)
    {
        perror("msgque_key fail");
    }
    else
    {
        perror("msgque_key");
    }

    // 获取消息队列msgid
    resource.msgque_id = msgget(msgque_key, IPC_CREAT | 0777);
    if (resource.msgque_id < 0)
    {
        perror("resource.msgque_id fail");
    }
    else
    {
        perror("resource.msgque_id");
    }

    // 创建共享内存---------------

    // 获取共享内存key
    key_t shmsg_key = ftok("/home", 123);
    if (shmsg_key < 0)
    {
        perror("shmsg_key");
    }
    else
    {
        perror("shmsg_key");
    }

    // 获取共享内存shm_id

    resource.shm_id = shmget(shmsg_key, sizeof(Shared_memory) * 100, IPC_CREAT | 0777);
    if (resource.shm_id < 0)
    {
        perror("resource.shm_id");
    }
    else
    {
        perror("resource.shm_id");
    }

    // 映射共享内存
    resource.shm_map_poi = (Shared_memory *)shmat(resource.shm_id, NULL, 0);
    if (resource.shm_map_poi == (Shared_memory *)-1)
    {
        perror("resource.shm_map_poi");
    }
    else
    {
        perror("resource.shm_map_poi");
    }

    resource.flag = 1;

    return 0;
}

// 退出资源摧毁
int Destroy()
{
    // printf("22\n");
    // 下线删除数据
    delete_info();
    // printf("22\n");

    // printf("11\n");
    // 回收线程
    pthread_cancel(resource.read_id);
    // pthread_cancel(resource.write_id);
    // printf("11\n");

    // pthread_join(resource.write_id, NULL);
    pthread_join(resource.read_id, NULL);

    // 下线通知
    signal(12, SIG_IGN);
    system("killall -12 test");

    // 摧毁消息队列
    struct shmid_ds ipc_info;
    shmctl(resource.shm_id, IPC_STAT, &ipc_info);
    if (ipc_info.shm_nattch == 1)
    {
        shmctl(resource.shm_id, IPC_RMID, NULL);
        msgctl(resource.msgque_id, IPC_RMID, NULL);
    }
}

int main(int argc, char const *argv[])
{

    // 资源准备,打开文件目录,消息队列以及,共享内存等
    Prepare_for();

    // 录入自己的信息
    resource.my_info.pid = getpid();
    printf("我的pid=%d\n", resource.my_info.pid);
    strcpy(resource.my_info.name, argv[1]);
    node_info();

    printf_friends();

    // 上线通知信号10
    signal(10, sig_up);

    // 下线通知信号12
    signal(12, sig_down);

    signal(10, SIG_IGN);
    system("killall -10 test");
    signal(10, sig_up);

    // 线程2收消息----------------------------------------------
    pthread_create(&resource.read_id, NULL, rcv_msg, NULL);

    // 主线程发送消息--------------------------------------------
    // pthread_create(&resource.write_id, NULL, send_msg, NULL);
    send_msg(NULL);

    // rcv_msg(NULL);

    // 退出资源摧毁
    Destroy();
    return 0;
}

进程通信.h

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 共享内存结构体
typedef struct Shared_memory
{
    pid_t pid;
    char name[32];
} Shared_memory;

struct msgbuf
{
    long mtype;
    char data[100];
} buf;

typedef struct Resources
{
    int msgque_id;
    int shm_id;
    Shared_memory *shm_map_poi;
    int flag;
    pthread_t read_id;
    pthread_t write_id;
    Shared_memory my_info;
} Resources;

// 各类资源准备结构体
Resources resource;
// 主体函数--------------------------------------------------------

// 资源准备,打开文件目录,消息队列以及,共享内存等
int Prepare_for();

// 线程1发送消息
void *send_msg(void *arg);

// 线程2接受消息
void *rcv_msg(void *arg);

// 退出资源摧毁
int Destroy();

// 功能函数-----------------------------------------------------------
// 上线告知所有进行
void sig_up(int sig);

// 下线通知所有进程
void sig_down(int sig);

// 读取在线好友
int printf_friends();

// 上线录入数据
int node_info();

// 下线删除数据
int delete_info();

进程通信功能函数.c

#include "进程通信.h"
// 上线告知所有进行
void sig_up(int sig)
{
    printf("你的好友已上线\n");
    printf_friends();
}

// 下线通知所有进程
void sig_down(int sig)
{
    printf("你的好友已下线\n");
    printf_friends();
}

// 读取在线好友
int printf_friends()
{
    Shared_memory *temp_friend = resource.shm_map_poi;
    int i = 1;
    printf("您的在线好友:\n");
    while (1)
    {
        i++;
        if (i == 100)
        {
            break;
        }
        if (temp_friend->pid == 0)
        {
            continue;
        }
        else
        {
            if (strcmp(temp_friend->name, resource.my_info.name) != 0)
            {
                printf("pid=%d %s(在线)\n", temp_friend->pid, temp_friend->name);
            }
        }
        // printf("%d\n", i);
        temp_friend++;
    }
}

// 上线录入数据
int node_info()
{
    int i = 1;
    Shared_memory *temp_friend = resource.shm_map_poi;
    while (1)
    {
        if (temp_friend->pid == 0)
        {
            *temp_friend = resource.my_info;
            break;
        }

        temp_friend++;
        i++;
        if (i == 100)
        {
            break;
        }
    }
}

// 下线删除数据
int delete_info()
{
    int i = 1;
    Shared_memory *temp_friend = resource.shm_map_poi;
    while (1)
    {
        if (strcmp(temp_friend->name, resource.my_info.name) == 0)
        {
            memset(temp_friend, 0, sizeof(Shared_memory));
            break;
        }
        temp_friend++;
        i++;
        if (i == 100)
        {
            break;
        }
    }
}

---------------------------------------------------------------------------------------------------------------------------------

这还一个写的比较乱的。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
struct people
{
    pid_t pid;
    char name[32];
    int flag;
    int flag2;
} friend;

struct msgbuf
{
    long mtype;//这个必须有消息队列就是根据type值区分不同消息的
    char bata[100];//大小随便改
} buf;//消息队列指定结构体。
int msg_id;
struct people *friend_list;


int printf_friends();

struct people *add_friend_list();
struct people *add_friend_list()
{
    struct people *temp_friend = friend_list;
    int i = 0;
    while (1)
    {
        if (temp_friend->pid == 0)
        {
            *temp_friend = friend;

            return temp_friend;
        }
        else
        {
            if (strcmp(temp_friend->name, friend.name) == 0)
            {
                *temp_friend = friend;
                return temp_friend;
            }
        }
        temp_friend++;
    }

    return (struct people *)-1;
}

void Signal_registration(int sig);
void Signal_registration(int sig)
{
    struct people *temp_friend = friend_list;

    int i = 0;
    while (1)
    {
        if (temp_friend->pid == 0)
        {
            return;
        }
        else
        {
            if (temp_friend->flag2 == 0 && strcmp(temp_friend->name, friend.name) != 0)
            {
                printf("您的好友:%s已上线\n", temp_friend->name);
                printf_friends();
                return;
            }
        }
        temp_friend++;
    }
}

void Signal_registration_down(int sig);
void Signal_registration_down(int sig)
{
    struct people *temp_friend = friend_list;

    // int i = 0;
    while (1)
    {
        if (temp_friend->pid == 0)
        {

            return;
        }
        else
        {
            if (temp_friend->flag2 == 0 && strcmp(temp_friend->name, friend.name) != 0)
            {
                printf("您的好友:%s已下线\n", temp_friend->name);
                temp_friend->flag = 0;
                printf_friends();
                return;
            }
        }
        temp_friend++;
    }
}

int printf_friends()
{
    struct people *temp_friend = friend_list;
    int i = 0;
    printf("您的在线好友:\n");
    while (1)
    {
        if (temp_friend->pid == 0)
        {
            return 0;
        }
        else
        {
            if (temp_friend->flag == 1 && strcmp(temp_friend->name, friend.name) != 0)
            {
                printf("%d.%s在线\n", i + 1, temp_friend->name);
            }
        }
        temp_friend++;
    }
}

void send_mas_name(char *name);
void send_mas_name(char *name)
{
    if (friend_list->pid == 0)
    {
        printf("您没有好友,发送失败");
        return ;
    }
    struct people *temp_friend = friend_list;
    while (1)
    {
        if (strcmp(temp_friend->name, name) == 0)
        {
            char rcvfriend[100];
            key_t key = ftok("/home", 123);
            if (key > 0)
            {
                // perror("获取成功");
            }
            else
            {
                perror("获取失败");
            }
            msg_id = msgget(key, IPC_CREAT | 0777);
            if (msg_id < 0)
            {
                perror("消息队列创建失败");
            }
            printf("请输入您要发送的消息:");
            scanf("%s", buf.bata);
            buf.mtype=temp_friend->pid;
            int res = msgsnd(msg_id, &buf, strlen(buf.bata), IPC_NOWAIT);
            if (res == 0)
            {

                // perror(" msgsnd ok");
            }
            sprintf(rcvfriend, "kill -14 %d ", temp_friend->pid);
            system(rcvfriend);
            return ;
        }
        temp_friend++;
    }
}

void fun(struct people *my_info);
void fun(struct people *my_info)
{
    int operat_exti;
    while (1)
    {
        printf_friends();
        printf("是否需要退出\n");
        printf("1、退出\n");
        printf("2、发送消息\n");
        scanf("%d", &operat_exti);
        if (operat_exti == 1)
        {
            my_info->flag = friend.flag = 0;
            my_info->flag2 = 0;
            system("killall -10 test");
            my_info->flag2 = 1;
            break;
        }
        if (operat_exti == 2)
        {
            char msg[1024];
            char name[32];
            printf("发送给谁:\n");
            scanf("%s", name);
            send_mas_name(name);
        }
        // printf_friends();
    }
}

void rcv_fun(int sig)
{
    key_t key = ftok("/home", 123);
    if (key > 0)
    {
        // perror("获取成功");
    }
    else
    {
        perror("获取失败");
    }
    msg_id = msgget(key, IPC_CREAT | 0777);
    if (msg_id < 0)
    {
        perror("消息队列创建失败");
    }
    memset(buf.bata,0,sizeof(buf));
    buf.mtype=getpid();
    int res=msgrcv(msg_id,&buf,sizeof(buf.bata),buf.mtype,0);
    printf("收到消息:%s\n",buf.bata);
    getchar();
}

int main(int argc, char const *argv[])
{
    friend.pid = getpid();
    printf("friend.pid =%d\n",friend.pid);
    strcpy(friend.name, argv[1]);
    friend.flag = 1;  // 上线
    friend.flag2 = 1; // 正常

    //------------------共享空间写入---------------------------

    key_t key = ftok("/home", 321);
    if (key == -1)
    {
        perror("key");
    }
    else
    {
        // printf("key success\n");
    }

    int shmid = shmget(key, 4096, IPC_CREAT | 0777);
    if (shmid == -1)
    {
        perror("shmget");
    }
    else
    {
        // printf("shmget success\n");
    }

    friend_list = (struct people *)shmat(shmid, NULL, 0);

    struct people *my_info = add_friend_list();

    if (my_info == (struct people *)-1)
    {
        perror("add_friend_list fail");
    }
    else
    {
        // printf("add_friend_list success\n");
    }

    //-----------------上线通知------------------------------------
    signal(12, Signal_registration);
    my_info->flag2 = 0;
    system("killall -12 test");
    my_info->flag2 = 1;
    //-----------------读取消息---------------------------------
    signal(14, rcv_fun);

    //----------------下线通知----------------------------------
    signal(10, Signal_registration_down);
    fun(my_info);
    //

    //----------------------退出判断是否销毁共享内存------------------
    struct shmid_ds ipc_info;
    shmctl(shmid, IPC_STAT, &ipc_info);
    if (ipc_info.shm_nattch == 1)
    {
        shmctl(shmid, IPC_RMID, NULL);
        msgctl(msg_id,IPC_RMID,NULL);
    }

    return 0;
}

你可能感兴趣的:(C语言,leetcode,算法)