当前位置:网站首页>内核与用户空间通过字符设备通信

内核与用户空间通过字符设备通信

2022-08-11 05:23:00 丶随心

kernel空间代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/io.h> //ioremap()
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "cdev_demo"

static struct cdev *pdev = NULL;
static   dev_t dev;
static int major = 0;
static int minor = 2;
static int count = 2;

static struct class* led_class;

#define GPL2_PA_BASE    0X11000100
#define rGPL2CON (*GPL2CON)
#define rGPL2DAT (*GPL2DAT)

static unsigned int *GPL2CON = NULL;
static unsigned int *GPL2DAT = NULL;

#define BUF_SIZE        (1024)
static char kbuf[BUF_SIZE];
static int  buf_count = 0;

static int cdev_demo_open(struct inode * inode, struct file * file)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
static int cdev_demo_release(struct inode *inode, struct file * file)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
static ssize_t cdev_demo_read(struct file * file, char __user * buffer, size_t size, loff_t * loff)
{
    printk("%s,%d\n",__func__,__LINE__);

    if(0 == buf_count){
        return -EAGAIN;
    }

    if(buf_count < size){
        size = buf_count;
    }

    if(size == copy_to_user(buffer,kbuf,size)){
        return -EAGAIN;
    }

    buf_count  = 0;

    return size;

}

static ssize_t cdev_demo_write(struct file * file, const char __user * buffer, size_t size, loff_t * loff)
{
    printk("%s,%d\n",__func__,__LINE__);
    printk("buffer=%s   size=%d\n",buffer,size);
    if(size >BUF_SIZE){
        return -ENOMEM;
    }

    if(size == copy_from_user(kbuf,buffer,size)){
        return -EAGAIN;
   }

    buf_count = size;
    return size;
}
static struct file_operations fops ={
    .owner   = THIS_MODULE,
    .open    = cdev_demo_open,
    .release = cdev_demo_release,
    .read    = cdev_demo_read,
    .write   = cdev_demo_write,
};

static int __init cdev_demo_init(void)
{
    int ret;

    printk("%s,%d\n",__func__,__LINE__);

    pdev = cdev_alloc();
    if(NULL == pdev){
        printk("cdev_alloc failed.\n");
        return -ENOMEM;
    }

    cdev_init(pdev,&fops);

    ret = alloc_chrdev_region(&dev,minor,count,DEVICE_NAME);
    if(ret){
        printk("alloc_chrdev_region failed.\n");
        goto ERROR_CDEV;
    }
    major = MAJOR(dev);
    printk("MAJOR Number is %d\n",MAJOR(dev));
    printk("MINOR Number is %d\n",MINOR(dev));

    ret = cdev_add(pdev, dev,count);
    if(ret) {
        printk("cdev_add failed.\n");
        goto  ERROR_ADD;
    }
    
    led_class = class_create(THIS_MODULE, "module_test3");
    device_create(led_class, NULL, dev, NULL, DEVICE_NAME);

    /*if (!request_mem_region(GPL2_PA_BASE, 8, "GPL2_BASE")) {
        printk(KERN_ERR "request_mem_region failed!\n");
        goto ERROR_DEVICE;
    }
    
    GPL2CON = ioremap(GPL2_PA_BASE, 8);
    GPL2DAT = GPL2CON + 1;

    rGPL2CON = 0X11111111;
    rGPL2DAT = (0 << 0);

    printk("GPL2CON:%p\n", GPL2CON);
    printk("GPL2DAT:%p\n", GPL2DAT);*/
    return 0;

ERROR_DEVICE:
    cdev_del(pdev);

ERROR_ADD:
    unregister_chrdev_region(dev,count);
ERROR_CDEV:
    cdev_del(pdev);
    return ret;
}
static void __exit cdev_demo_exit(void)
{
        printk("%s,%d\n",__func__,__LINE__);
      /*rGPL2DAT = (0 << 0);
    iounmap(GPL2CON);
    release_mem_region(GPL2_PA_BASE, 8);*/

    device_destroy(led_class, dev);    
    class_destroy(led_class);
    
    unregister_chrdev_region(MKDEV(major,minor),count);

    cdev_del(pdev);
}

module_init(cdev_demo_init);
module_exit(cdev_demo_exit);
MODULE_LICENSE("GPL");

用户空间代码:

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


#include <errno.h>

#define BUFFER_SIZE  (1024)
int main(int argc,char* argv[])
{
    char *dev = "/dev/cdev_demo";

    int fd = open(dev,O_RDWR | O_NONBLOCK);
    if(0 > fd){
        perror("open\n");
        return -1;
    }

    printf("open %s ",dev);


    char buf[] = "string for read and write";
    int ret = write(fd,buf,sizeof(buf));
    printf(" write ret = %d,errno = %d\n",ret,errno);

    char rbuf[BUFFER_SIZE];
    memset(rbuf,0,BUFFER_SIZE);
    ret  = read(fd,rbuf,BUFFER_SIZE);
    printf("read buf = %s \n",rbuf);
    printf("read ret = %d,errno = %d\n",ret,errno);

    close(fd);
    return  0;
}

原网站

版权声明
本文为[丶随心]所创,转载请带上原文链接,感谢
https://blog.csdn.net/suixin______/article/details/117132893