kpipe实现进程间通信

源代码:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/cdev.h>  

//module_param(dev_major, int, S_IRUGO);
#define MY_DEV_MAJOR        260     /*预设的mem的主设备号*/
static int dev_major = 0; //MY_DEV_MAJOR;  

#define MY_DEV_NR_DEVS      2       /*设备数*/  

#define CHAR_DEV_NAME       "kpipe"

/*
‘k‘为幻数,要按照Linux内核的约定方法为驱动程序选择ioctl编号,
应该首先看看include/asm/ioctl.h和Documentation/ioctl-number.txt这两个文件.

对幻数的编号千万不能重复定义,如ioctl-number.txt已经说明‘k‘的编号已经被占用的范围为:
‘k‘    00-0F    linux/spi/spidev.h    conflict!
‘k‘    00-05    video/kyro.h        conflict!
所以我们在这里分别编号为0x1a和0x1b
*/
#define CMD_MAGIC   ‘k‘
#define MEM_CMD1    _IO(CMD_MAGIC, 0x1a)
#define MEM_CMD2    _IO(CMD_MAGIC, 0x1b)
#define MEM_CMD3    _IO(CMD_MAGIC, 0x1c)

#if 1
#define MAX_UID_NUM     32

typedef struct tagUSER_MSG_INFO
{
    int  uid;
    int  param1;
    int  param2;
    int  param3;
    char *msg;
}USER_MSG_INFO;

typedef struct tagUSER_QUEUE_INFO
{
    int  rd_ptr;
    int  wt_ptr;
    int  max_msg;
    int  msg_max_len;
    char *msg_queue;
}USER_QUEUE_INFO;

USER_QUEUE_INFO usr_queue[MAX_UID_NUM];

static int user_queue_init(void)
{
    int i;

    for(i = 0; i < MAX_UID_NUM; i++) {
        memset(&usr_queue[i], 0, sizeof(USER_QUEUE_INFO));
    }
    return 0;
}

static int user_queue_alloc(int uid, int max_msg, int msg_max_len)
{
    int total_size;

    if (uid >= MAX_UID_NUM) return -1;
    if (max_msg < 1 || msg_max_len < 1) return -1;
    if (usr_queue[uid].msg_queue != NULL) return -2;

    total_size = max_msg * msg_max_len;
    usr_queue[uid].msg_queue = kmalloc(total_size, GFP_KERNEL);
    if (NULL == usr_queue[uid].msg_queue) return -3;

    usr_queue[uid].max_msg = max_msg;
    usr_queue[uid].msg_max_len = msg_max_len;
    usr_queue[uid].rd_ptr = 0;
    usr_queue[uid].wt_ptr = 0;

    return 0;
}

static int user_queue_push(USER_MSG_INFO *usr_msg)
{
    int uid;
    char *ptr;

    if (NULL == usr_msg) return -1;
    uid = usr_msg->uid;
    if (usr_queue[uid].msg_queue == NULL) return -2;

    if ( (usr_queue[uid].wt_ptr + 1) % usr_queue[uid].max_msg == usr_queue[uid].rd_ptr)
        return -3; // full

    ptr = usr_queue[uid].msg_queue + usr_queue[uid].wt_ptr * usr_queue[uid].msg_max_len;
    memset(ptr, 0, usr_queue[uid].msg_max_len);
    copy_from_user((int *)ptr, (int *)usr_msg->msg, usr_queue[uid].msg_max_len);
    usr_queue[uid].wt_ptr = (usr_queue[uid].wt_ptr + 1) % usr_queue[uid].max_msg;

    return 0;
}

static int user_queue_pop(USER_MSG_INFO *usr_msg)
{
    int uid;
    char *ptr;

    if (NULL == usr_msg) return -1;
    uid = usr_msg->uid;
    if (usr_queue[uid].msg_queue == NULL) return -2;

    if ( usr_queue[uid].rd_ptr == usr_queue[uid].wt_ptr)
        return -3; // empty

    ptr = usr_queue[uid].msg_queue + usr_queue[uid].rd_ptr * usr_queue[uid].msg_max_len;
    copy_to_user((int *)usr_msg->msg, (int *)ptr, usr_queue[uid].msg_max_len);
    usr_queue[uid].rd_ptr = (usr_queue[uid].rd_ptr + 1) % usr_queue[uid].max_msg;

    return 0;
}

static int user_queue_destroy(void)
{
    int i;

    for(i = 0; i < MAX_UID_NUM; i++) {
        usr_queue[i].max_msg = 0;
        if (NULL != usr_queue[i].msg_queue)
            kfree(usr_queue[i].msg_queue);
        usr_queue[i].msg_queue = NULL;
    }
    return 0;
}

#endif

#if 1
int my_dev_open(struct inode *inode, struct file *filp)
{
    return 0;
}  

int my_dev_release(struct inode *inode, struct file *filp)
{
    return 0;
}
static int my_dev_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{
    USER_MSG_INFO user_msg;
    int ret = 0;

    switch(cmd)
    {
        case MEM_CMD1: // init mq for uid
            if(copy_from_user(&user_msg,  (int *)arg, sizeof(USER_MSG_INFO)))
                return -EFAULT;

            ret = user_queue_alloc(user_msg.uid, user_msg.param1, user_msg.param2);
            break;

        case MEM_CMD2: // send msg to uid
            if(copy_from_user(&user_msg,  (int *)arg, sizeof(USER_MSG_INFO)))
                return -EFAULT;

            ret = user_queue_push(&user_msg);
            break;

        case MEM_CMD3: // get msg from uid
            if(copy_from_user(&user_msg,  (int *)arg, sizeof(USER_MSG_INFO)))
                return -EFAULT;

            ret = user_queue_pop(&user_msg);
            break;
    }

    return ret;
}

static const struct file_operations my_dev_fops =
{
    .owner = THIS_MODULE,
    .unlocked_ioctl = my_dev_ioctl,
    .open = my_dev_open,
    .release = my_dev_release,
};  

struct class *pclass = NULL;  

struct cdev my_dev;   

static int my_dev_init(void)
{
    int result;
    dev_t devno = MKDEV(dev_major, 0);  

    if (dev_major) { /* 静态申请设备号*/
        result = register_chrdev_region(devno, 2, CHAR_DEV_NAME);
    } else { /* 动态分配设备号 */
        result = alloc_chrdev_region(&devno, 0, 2, CHAR_DEV_NAME);
        dev_major = MAJOR(devno);
    }   

    if (result < 0)
        return result;  

    cdev_init(&my_dev, &my_dev_fops);
    my_dev.owner = THIS_MODULE;
    my_dev.ops = &my_dev_fops;
    cdev_add(&my_dev, MKDEV(dev_major, 0), MY_DEV_NR_DEVS);  

    pclass = class_create(THIS_MODULE, CHAR_DEV_NAME);
    if (IS_ERR(pclass))
    {
        printk("class_create failed!/n");
        goto failed;
    }  

    user_queue_init();
    device_create(pclass, NULL, devno, NULL, CHAR_DEV_NAME);
    return 0;  

failed:
    cdev_del(&my_dev);
    unregister_chrdev_region(devno, 1);
    return result;
}  

static void my_dev_exit(void)
{
    device_destroy(pclass, MKDEV(dev_major, 0));
    class_destroy(pclass);

    cdev_del(&my_dev);
    unregister_chrdev_region(MKDEV(dev_major, 0), 2);
    user_queue_destroy();
}  

#endif

MODULE_AUTHOR("derek.yi");
MODULE_LICENSE("GPL");  

module_init(my_dev_init);
module_exit(my_dev_exit);  

测试代码:

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define CMD_MAGIC   ‘k‘
#define MEM_CMD1    _IO(CMD_MAGIC, 0x1a) // init
#define MEM_CMD2    _IO(CMD_MAGIC, 0x1b) // write
#define MEM_CMD3    _IO(CMD_MAGIC, 0x1c) // read

typedef struct tagUSER_MSG_INFO
{
    int  uid;
    int  param1;
    int  param2;
    int  param3;
    char *msg;
}USER_MSG_INFO;

#define _APP_001_

#ifdef _APP_001_
int main()
{
    int fd;
    int ret;
    char buff[256];
    USER_MSG_INFO usr_msg;

    fd = open("/dev/kpipe", O_RDWR);
    if( fd < 0 ) {
        printf("open kpipe WRONG!\n");
        return 0;
    }

    usr_msg.uid = 0;
    usr_msg.param1 = 64; // max msg
    usr_msg.param2 = 128; // max len

    ret = ioctl(fd, MEM_CMD1, &usr_msg);
    printf("ioctl: ret=%d\n", ret);

    usr_msg.msg = &buff[0];
    sprintf(buff, "hello,pipe\n");
    ret = ioctl(fd, MEM_CMD2, &usr_msg);
    printf("ioctl: ret=%d\n", ret);

    usr_msg.msg = &buff[0];
    memset(buff, 0, 256);
    ret = ioctl(fd, MEM_CMD3, &usr_msg);
    printf("ioctl: ret=%d rdata=%s\n", ret, buff);

    close(fd);
    return 0;
}

#endif
时间: 2024-11-05 05:18:38

kpipe实现进程间通信的相关文章

Linux进程间通信总结

Linux进程间通信总结 1. 管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: (1)管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: (2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): (3)单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. (4)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出

Xenomai 进程间通信方式

Xenomai 进程间通信方式分成Xenomai域内的IPC以及Xenomai域和Linux域之间的IPC, 目前采用的rtipc(RTDM驱动)的方式,主要是给用户空间提供socket接口,实时应用 通过调用对应的接口可以避免切换到Linux域而导致实时性降低.rtipc对应了三个协议: XDDP (Xenomai域和Linux域之间的IPC) IDDP和BUFP (Xenomai域内的IPC) 另外,原有的RT_PIPE机制仍旧支持,但从Xenomai 3开始就不支持了. http://ww

31、互斥锁与进程间通信

我们之前做了多进程并发,那么你们有没有发现问题.如果说多个进程共享同一个数据,比如抢火车票大家同时在客户端查看同时购买会出现什么问题呢?今天我们将讲述进程锁还有进程间通信,进程之间彼此隔离,他们需要一个第三方联系起来. 一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,没错,速度是慢了,牺牲了速度而保证了数据安全. 1.上厕所 先举个通俗易懂

一起talk C栗子吧(第八十五回:C语言实例--使用信号进行进程间通信二)

各位看官们,大家好,上一回中咱们说的是使用信号进行进程间通信的样例,这一回咱们接着上一回的内容,继续说该样例.闲话休提.言归正转. 让我们一起talk C栗子吧. 我们在上一回中举了使用信号进行进程间通信的样例,在该样例中.我们通过终端发出信号.当进程收到该信号后让它运行系统对信号定义的默认动作.这一回.我们再来举一个使用信号进行进程间通信的样例,只是.我们发送和处理信号的方式和上一回的样例不一样.在接下来的样例中,我们在一个进程中使用kill产生信号.在另外一个进程中接收而且依照自己的方式处理

进程间通信 详解

进程间通信(IPC)介绍 进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息. IPC的方式通常有管道(包括无名管道和命名管道).消息队列.信号量.共享存储.Socket.Streams等.其中 Socket和Streams支持不同主机上的两个进程IPC. 以Linux中的C语言编程为例. 一.管道 管道,通常指无名管道,是 UNIX 系统IPC最古老的形式. 1.特点: 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端.

(转载)linux下的僵尸进程处理SIGCHLD信号Linux环境进程间通信(五): 共享内存(下)

Linux环境进程间通信(五): 共享内存(下) 在共享内存(上)中,主要围绕着系统调用mmap()进行讨论的,本部分将讨论系统V共享内存,并通过实验结果对比来阐述两者的异同.系统V共享内存指的是把所有共享数据放在共享内存区域(IPC shared memory region),任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面. 系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内

st_vio——进程间通信接口抽象结构体

工作忙,学习忙,但还是得随便写点. st_vio,顾名思义,应该是指virtual IO,即虚拟IO.根据代码里的注释,这个是一个高度抽象的进程间通信接口结构体,mysql中,如果不是用C++类来抽象,那么就是用含函数指针的结构体来抽象,这也是C语言最常用的习惯. struct st_vio { my_socket sd; /* my_socket - real or imaginary套接字 */ HANDLE hPipe/* 看风格应该只用于Windows系统 */; my_bool loc

PHP进程及进程间通信

一.引言 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.换句话说就是,在系统调度多个cpu的时候,一个程序的基本单元.进程对于大多数的语言都不是一个陌生的概念,作为"世界上最好的语言PHP"当然也例外. 二.环境 php中的进程是以扩展的形式来完成.通过这些扩展,我们能够很轻松的完成进程的一系列动作. pcntl扩展:主要的进程扩展,完成进程创建于等待操作. posix扩展:完成posix兼容机通用api,如获取进程id,杀死进程等. sysvmsg扩展:实现system

Android开发——进程间通信之AIDL(二)

0.  前言 不论是Android还是其他操作系统,都会有自己的IPC机制,所谓IPC(Inter-Process Communication)即进程间通信.首先线程和进程是很不同的概念,线程是CPU调用的最小单元,进程一般在PC和移动设备上指一个程序或者一个应用,一个进程可以包含多个线程. IPC方式有很多,在Android中常用的IPC方式包括Bundle.文件.Messenger.AIDL.ContentProvider和Socket等方式. Android开发--进程间通信之AIDL(一