首页 > 系统相关 >linux c ipc机制

linux c ipc机制

时间:2022-12-09 12:00:38浏览次数:35  
标签:__ ipc int sbuf key linux 机制 include buff

ipc

ipc 意思就是 进程间通信机制的简称
在linux(centos)环境下 使用 ipcs(信息查看),ipcrm(删除), ipcmk(创建)
通过指令 ipcs 查看, linux 支持的IPC机制有三种

  1. Message Queues: 消息队列
  2. Shared Memory Segments: 共享内存段
  3. Semaphore Arrays: 信号量数组
[root@process_comm#] ipcs 

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x4201032a 0          root       666        184          2           

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      

------ Semaphore Arrays --------
key        semid      owner      perms      nsems  

消息队列

代码示例

代码如下: 使用 gcc -o recv ipc_que_recv.c, gcc -o send ipc_que_send.c 编译各自代码得到 recvsend,分别运行
ipc_que_recv.c

#include <stdio.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>

int create_msg_queue() {
    /**
     * 该方法通过指定参数, 生成对应的 唯一key id标识
     * extern key_t ftok (const char *__pathname, int __proj_id) __THROW;
     * __pathname: 存在的路径名或者文件,必须存在,否则返回错误
     * __proj_id: 自己约定, 在unix中取值 1~255
     */
    key_t _key = ftok("temp113", 66);
    if(_key < 0) {
        printf("error to ftok \n");
        return;
    }
    printf("ftok _key: 0x%0x \n", _key);
    /**
     * 该方法主要是为了根据 __key 查询消息队列是否已经创建
     * extern int msgget (key_t __key, int __msgflg) __THROW;
     * __key: 消息队列的对象的关键字(key)
     * __msgflg: 对条件进行判断
     * 0666: 第一位表示 条件判断的处理方法
     *       第二位表示 当前用户的权限, 读.写.可执行
     *       第三位表示 group用户组权限
     *       第四位表示 其它用户的权限
     * ret: -1 失败, 权限被拒绝
     *       0 成功  
     *  详见: rttno-base.h
     * /proc/sys/kernel/msgmax  一个消息的字节大小
     * /proc/sys/kernel/msgmnb  存放消息队列的总字节数
     * /proc/sys/kernel/msgmni  系统的消息队列数目
     * 查看系统支持消息队列数量, 
    */  
    // int msgid = msgget(_key, IPC_CREAT | IPC_EXCL | 0666);
    int msgid = msgget(_key, IPC_CREAT | 0666);
    if(msgid < 0)
	{
		printf("error msgid %d \n", msgid);
        // errno 是记录系统的最后一次错误代码
		printf("%d : %s\n", errno, strerror(errno));
		return 1;
	}
    printf("msgget msgid: 0x%0x \n", msgid);
    return msgid;
}
struct msgbuf
{
	long mtype;
	unsigned char buff[92];
};
int main(int argc, char const *argv[])
{
    int msg_id = create_msg_queue();
    struct msgbuf sbuf;
    sbuf.mtype = 0x01;
    int cnt = 0;
    while(1) {
        cnt ++;
        memset(sbuf.buff, 0x0, sizeof(sbuf.buff));
        /**
         * 该函数为接收队列消息
         * extern ssize_t msgrcv (int __msqid, void *__msgp, size_t __msgsz, long int __msgtyp, int __msgflg);
         * __msqid: msg_id
         * __msgp: 接收数据的缓冲区
         * __msgsz: 接收数据缓冲区的大小
         * __msgtyp: 接收数据的类型, 就是可以通过三四个以上的进程之间的通信,用类型表示要发送给指定的消费者
         *   0, 函数不做类型检查返回队列中最旧的内容
         *  >0, 接收类型等于 __msgtyp 的第一个消息
         *  <0, 接收类型等于或者小于msgtyp绝对值的第一个消息
         * __msgflg: 控制函数行为
         *  IPC_NOWAIT: 队列为空,返回 ENOMSG( No message of desired type), 并将控制权交回调用函数的进程, 如果不指定, 那函数将一直处于阻塞状态
         *  MSG_NOERROR: 如何函数取得的消息长度大于 __msgsz, 将只返回 msgsz长度的信息, 剩下的会被丢弃, 如果不指定这个函数, 将被返回状态码E2BIG(Argument list too long)
         *  IPC_EXCEPT: 与msgtype配合使用返回队列中第一个类型不为msgtype的消息
         * ret: -1, 读取错误, 错误存在 error 中
         *       否则返回实际读取的数据长度
         */
        int rlen = msgrcv(msg_id, &sbuf, sizeof(sbuf.buff), 0x02, 0);
        if(rlen < 0) {
            printf("%d : %s", errno, strerror(errno));
            return -1;
        } else {
            printf("[%d]%d:%0x %0x %0x %0x\n", cnt, rlen, sbuf.buff[0],sbuf.buff[20],sbuf.buff[90],sbuf.buff[91]);
        }

        usleep(1000*100);
    }
    return 0;
}

ipc_que_send.c

#include <stdio.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>

int get_msg_queue() {
    key_t _key = ftok("temp113", 66); 
	if(_key < 0)
	{
		printf("%d : %s",errno,strerror(errno));
		return -1;
	}

	int msg_id = msgget(_key, IPC_CREAT);
    printf("msgid: %d \n", msg_id);
	return msg_id;
}
struct msgbuf
{
	long mtype;
	unsigned char buff[92];
};
int main(int argc, char const *argv[])
{
    int msg_id = get_msg_queue();
    struct msgbuf sbuf;
    memset(sbuf.buff, 'c', sizeof(sbuf.buff));
    unsigned char cnt = 0;
    sbuf.mtype = 0x02;
    sbuf.buff[0] = 0x0;
    sbuf.buff[91] = 'a';
    while (1)
    {
        sbuf.buff[0] = cnt;
        cnt++;
        /**
         * 该函数为向队列发送数据
         * extern int msgsnd (int __msqid, const void *__msgp, size_t __msgsz, int __msgflg);
         * __msgflg: 控制发送函数的行为, IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。
         * ret: 0 成功
         *     -1 errno
        */
        int res = msgsnd(msg_id, &sbuf, sizeof(sbuf.buff), 0);
        printf("[%d] res %d, rlen %d res: %0x %0x %0x %0x \n", cnt, res, sizeof(sbuf.buff),sbuf.buff[0], sbuf.buff[20], sbuf.buff[60], sbuf.buff[91]);
        sleep(1);
    }
    
    return 0;
}

实验探索结论

1.当消息队列一旦创建之后, 他是存在于内核系统的, 不限于用户态的程序, 也就是说用户态的程序不管是java还是c, 不管是运行还是不运行, 不管是两个进程还是更多的进程, 他都可以对消息队列进行收发数据的操作, 异或同一进程自发自收
2.消息队列在内核中的源码

标签:__,ipc,int,sbuf,key,linux,机制,include,buff
From: https://www.cnblogs.com/han-guang-xue/p/16968447.html

相关文章

  • Linux系统常见的三种设备分类!
    Linux系统中设备主要分为哪几类?在Linux中,设备主要分为三种,分别是:块设备、字符设备和网络设备,接下来通过这篇文章详细介绍一下。Linux系统中的设备可以分为字符设备......
  • itop3588开发板编译Linux源码包-修改成mipi显示
    打开​​Linux​​源码kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi中的设备树文件。如下图所示默认包含的头文件即是mipi显示:更多内容可以了解迅为35......
  • itop3568开发板在Linux系统中使用NPU
    下载rknpu2并拷贝虚拟机​​Ubuntu​​,如下图所示,RKNPU2提供了访问rk3568芯片NPU的高级接口。下载地址为“iTOP-3568开发板\02_【iTOP-RK3568开发板】开发资料\11_NPU使......
  • itop3568开发板在Linux系统中使用NPU
    下载rknpu2并拷贝虚拟机Ubuntu,如下图所示,RKNPU2提供了访问rk3568芯片NPU的高级接口。 下载地址为“iTOP-3568开发板\02_【iTOP-RK3568开发板】开发资料\11_NPU使用......
  • itop3588开发板编译Linux源码包-修改成mipi显示
    打开Linux源码kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi中的设备树文件。如下图所示默认包含的头文件即是mipi显示:更多内容可以了解迅为3588开发......
  • Linux命令后面常见的>/dev/null 解释
    https://blog.csdn.net/chest_/article/details/102727490https://blog.csdn.net/modi000/article/details/116237756?spm=1001.2101.3001.6650.1&utm_medium=distribute.......
  • Linux 操作命令 小笔记
    1.更改文件名名字mv要更改的文件名想要更改后的名字2.cat查看文件内容3-rm删除文件......
  • Linux操作系统之Linux命令的返回值
    前言①Linux操作系统中,无论是启动桌面程序还是在控制台终端执行命令,所有的程序在结束时,都会返回一个数字值,这个值叫做返回值,或者称为错误号( ErrorNumber )②在控制台终......
  • MySQL基础知识(二)-超详细 Linux安装MySQL5.7完整版教程及遇到的坑
    1.简介 我们经常会在Linux上安装MySQL数据库,但是安装的时候总是会这里错,那里错,不顺利,今天整理了一下安装流程,连续安装来了两遍,没有遇到什么大错误,基本上十分钟左右可以搞......
  • linux 命令行上传文件
    LinuxcommandlinetoolforuploadingfilesoverHTTPasmultipart/form-data?curl-F"file=@localfile;filename=nameinpost"url.com......