uio设备:发送中断&共享内存

1,内核代码

#include <linux/init.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <asm/io.h>
#include <linux/slab.h> /* kmalloc, kfree */
#include <linux/irq.h> /* IRQ_TYPE_EDGE_BOTH */
#include <asm/uaccess.h>  

#define STRING_LEN 256  

char global_buffer[STRING_LEN] = {0};

#if 1

static irqreturn_t my_interrupt(int irq, void *dev_id)
{
    struct uio_info *info = (struct uio_info *)dev_id;
    unsigned long *ret_val_add = (unsigned long *)(info->mem[0].addr);
    *ret_val_add = 222;
    printk("my_interrupt: %d \n" ,(int)(*ret_val_add));

    return IRQ_RETVAL(IRQ_HANDLED);
}

struct uio_info kpart_info = {
    .name = "kpart",
    .version = "0.1",
    .irq = 10, //unused
    .handler = my_interrupt, //unused
    .irq_flags = IRQ_TYPE_EDGE_RISING, //unused
};

static int drv_kpart_probe(struct device *dev);
static int drv_kpart_remove(struct device *dev);

static struct device_driver uio_dummy_driver = {
    .name = "kpart",
    .bus = &platform_bus_type,
    .probe = drv_kpart_probe,
    .remove = drv_kpart_remove,
};

#ifdef HW_ENABLE
struct button_irq_desc {
    int irq;
    int num;
    char *name;
};

static struct button_irq_desc button_irqs [] = {
    {8 , 1, "KEY0"},
    {11, 2, "KEY1"},
    {13, 3, "KEY2"},
    {14, 4, "KEY3"},
    {15, 5, "KEY4"},
};

static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
    struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

    unsigned long *ret_val_add = (unsigned long *)(kpart_info.mem[1].addr);
    *ret_val_add = button_irqs->num;

    printk("%s is being pressed ..... \n", button_irqs->name);

    uio_event_notify(&kpart_info);

    return IRQ_RETVAL(IRQ_HANDLED);
}
#endif    

static int drv_kpart_probe(struct device *dev)
{
    unsigned long *ret_val_addr;

    kpart_info.mem[0].addr = (unsigned long)kmalloc(1024, GFP_KERNEL);
    if(kpart_info.mem[0].addr == 0)
        return -ENOMEM;
    kpart_info.mem[0].memtype = UIO_MEM_LOGICAL;
    kpart_info.mem[0].size = 1024;

    ret_val_addr = (unsigned long *)(kpart_info.mem[0].addr);
    *ret_val_addr = 222;

    if(uio_register_device(dev, &kpart_info)){
        kfree((void *)kpart_info.mem[0].addr);
        return -ENODEV;
    }

#ifdef HW_ENABLE
    int i = 0 ,err = 0;
    for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
        err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_RISING,
                          button_irqs[i].name, (void *)&button_irqs[i]);
        if (err)
            break;
    }
#endif    

    return 0;
}  

static int drv_kpart_remove(struct device *dev)
{
    kfree((void *)kpart_info.mem[0].addr);
    uio_unregister_device(&kpart_info);
    return 0;
}

#endif

#if 1

static int user_cmd_proc(char *user_cmd)
{
    if(strncmp(user_cmd, "sendsig", 7) == 0) {
        unsigned long *ret_val_add = (unsigned long *)(kpart_info.mem[0].addr);
        *ret_val_add = 333;
        uio_event_notify(&kpart_info);
    }

    return 0;
}

static int my_proc_show(struct seq_file *seq, void *v)
{
    seq_printf(seq, "current kernel time is %ld\n", jiffies);
    seq_printf(seq, "last cmd: %s", global_buffer);

    return 0;
}

static int my_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, my_proc_show, inode->i_private);
} 

static ssize_t my_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
{
    if (count > 0) {
        printk("my_proc_write called\n");
        copy_from_user(global_buffer, buffer, count);
        user_cmd_proc(global_buffer);
    }

    return count;
} 

struct file_operations proc_fops =
{
    .open  = my_proc_open,
    .read  = seq_read,
    .write  = my_proc_write,
    .llseek  = seq_lseek,
    .release = single_release,
};

static struct proc_dir_entry *proc_dir = NULL;
static struct proc_dir_entry *proc_file = NULL;
static struct platform_device * uio_dummy_device;

static int __init proc_test_init(void)
{
    proc_dir = proc_mkdir("my_proc", NULL);
    if (!proc_dir) {
         printk(KERN_DEBUG"proc_mkdir failed");
         return 0;
    }

    proc_file = proc_create("buffer", 0666, proc_dir, &proc_fops);
    if (!proc_file) {
         printk(KERN_DEBUG"proc_create failed");
         return 0;
    }

    uio_dummy_device = platform_device_register_simple("kpart", -1, NULL, 0);
    driver_register(&uio_dummy_driver);   

    return 0;
}  

static void __exit proc_test_exit(void)
{
    remove_proc_entry("buffer", proc_dir);
    remove_proc_entry("my_proc", NULL);  

    platform_device_unregister(uio_dummy_device);
    driver_unregister(&uio_dummy_driver);
}
#endif

module_init(proc_test_init);
module_exit(proc_test_exit);
MODULE_AUTHOR("derek.yi");
MODULE_LICENSE("GPL");  

2,用户代码

#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>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/mman.h>  

#define UIO_DEV     "/dev/uio0" ///sys/class/uio/uio0/name: kpart

#define UIO_ADDR0     "/sys/class/uio/uio0/maps/map0/addr"
#define UIO_SIZE0     "/sys/class/uio/uio0/maps/map0/size"
#define UIO_ADDR1     "/sys/class/uio/uio0/maps/map1/addr"
#define UIO_SIZE1    "/sys/class/uio/uio0/maps/map1/size"

static char uio_addr_buf[16], uio_size_buf[16];

int main()
{
    int uio_fd, addr_fd, size_fd;
    int uio_size;
    void *uio_addr, *access_address;
    fd_set rd_fds, tmp_fds;
    int c, ret;

    uio_fd = open(UIO_DEV, O_RDWR);
    addr_fd = open(UIO_ADDR0, O_RDONLY);
    size_fd = open(UIO_SIZE0, O_RDONLY);

    if(addr_fd < 0 || size_fd < 0 || uio_fd < 0 ) {
        fprintf(stderr, "mmap: %s\n", strerror(errno));
        exit(-1);
    }

#if 0
    read(addr_fd, uio_addr_buf, sizeof(uio_addr_buf));
    read(size_fd, uio_size_buf, sizeof(uio_size_buf));
    uio_addr = (void*)strtoul(uio_addr_buf, NULL, 0);
    uio_size = (int)strtol(uio_size_buf, NULL, 0);
#endif

    access_address = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 0);
    if (access_address == (void*) -1 ) {
        fprintf(stderr, "mmap: %s\n", strerror(errno));
        exit(-1);
    }

    while (1) {
        FD_ZERO(&rd_fds);
        FD_SET(uio_fd, &rd_fds);
        tmp_fds = rd_fds;

        ret = select(uio_fd+1, &tmp_fds, NULL, NULL, NULL);
        if (ret > 0) {
            if (FD_ISSET(uio_fd, &tmp_fds)) {
                read(uio_fd, &c, sizeof(int));
                printf("current event count %d, data %d\n", c, *(int *)access_address);
            }
        }
    }

    close(uio_fd);

    return 0;
}

3,测试脚本

sudo modprobe uio
sudo insmod myuio.ko

echo "sendsig" > /proc/my_proc/buffer
cat /proc/my_proc/buffer

[email protected]:~/share/ldd5$ gcc app.c
[email protected]:~/share/ldd5$ sudo ./a.out
current event count 10, data 333
current event count 11, data 333
current event count 12, data 333
时间: 2024-10-03 12:47:26

uio设备:发送中断&共享内存的相关文章

c++共享内存(转载)

对于连个不同的进程之间的通信,共享内存是一种比较好的方式,一个进程把数据发送到共享内存中, 另一个进程可以读取改数据,简单记录一下代码 1 #define BUF_SIZE 256 2 TCHAR szName[]=TEXT("Global\\YourFileMappingObject"); //指向同一块共享内存的名字 3 4 int SetFileName(LPCTSTR str) 5 { 6 HANDLE hMapFile; 7 LPCTSTR pBuf; 8 9 hMapFil

共享内存实现大规模点积

项目打包下载 1 /* 2 * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. 3 * 4 * NVIDIA Corporation and its licensors retain all intellectual property and 5 * proprietary rights in and to this software and related documentation. 6 * Any use, repr

在向server发送请求时发生传输级错误。 (provider: 共享内存提供程序, error: 0 - 管道的还有一端上无不论什么进程。

作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/36425825 SQL Server 2008 + VS2010 用C#编写的代码,进行数据库还原的时候,出错: 错误内容: 在向server发送请求时发生传输级错误. (provider: 共享内存提供程序, error: 0 - 管道的还有一端上无不论什么进程. 解决方法: 将SQL链接语句构造成例如以下: string strLink = @"server=.;datab

在向服务器发送请求时发生传输级错误。 (provider: 共享内存提供程序, error: 0 - 管道的另一端上无任何进程。

作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/36425825 SQL Server 2008 + VS2010 用C#编写的代码,进行数据库还原的时候,出错: 错误内容: 在向服务器发送请求时发生传输级错误. (provider: 共享内存提供程序, error: 0 - 管道的另一端上无任何进程. 解决方法: 将SQL链接语句构造成如下: string strLink = @"server=.;database=Data

信号,信号量,锁,条件变量,消息通信,共享内存,RPC (一)

在实际项目当中,经常需要把一个功能分成多个子模块实现.那么,这些子模块之间该如何关联起来呢?静态地看,模块可以看作一组完成相同功能的函数:而动态地看,模块可以是一个独立的进程.线程或者一个中断服务或者信号服务例程.根据不同的具体业务实现,它们之间可能是静态调用.动态互斥.同步.唤醒等关系.静态的调用很好实现,上层的函数调用底层的函数即可.那么,动态互斥.同步.唤醒等关系,又该如何实现呢?这就设计到我们将要讨论的信号.进程间消息通信.共享内存.线程互斥同步条件变量.RPC等手段.下面就按照Linu

IPC通信之消息队列、信号量和共享内存

有三种IPC我们称作XSI IPC,即消息队列,信号量以及共享存储器.XSI IPC源自System V的IPC功能.由于XSI IPC不使用文件系统的命名空间,而是构造了它们自己的名字空间,为此常常受到批评. 相似之处:每个内核中的IPC结构都用一个非负整数的标识符加以引用.例如对一个消息队列发送或取消息,只需要知道其队列标识符.与文件标识符不同,IPC标识符不是小的整数,当一个IPC结构被创建,以后又被删除时,与这种结构相关的标识符连续加1,直至达到一个整形数的最大正值,然后又回转到0. 标

操作系统 进程间的通信 之 信号 消息队列 共享内存 浅析

[几个易混淆的相关概念] 进程互斥:指在多道程序环境下,每次只允许一个进程对临界资源进行访问. 进程同步:指多个相关进程在执行次序上的协调. 临界资源:在一段时间内只允许一个进程访问的资源. 临界区:每个进程中访问临界资源的那段代码. [进程通信] 现在常用的进程间通信方式有信号.信号量.消息队列.共享内存.通信,是一个广义的意义,不仅仅指传递一些 message.进程通信就是指不同进程之间进程数据共享和数据交换. [信号和信号量] 信号和信号量是不同的,他们虽然都可用来实现同步和互斥,但信号是

Boost:shared_memory_object --- 共享内存

什么是共享内存 共享内存是最快速的进程间通信机制.操作系统在几个进程的地址空间上映射一段内存,然后这几个进程可以在不需要调用操作系统函数的情况下在那段内存上进行读/写操作.但是,在进程读写共享内存时,我们需要一些同步机制. 考虑一下服务端进程使用网络机制在同一台机器上发送一个HTML文件至客户端将会发生什么: 服务端必须读取这个文件至内存,然后将其传至网络函数,这些网络函数拷贝那段内存至操作系统的内部内存. 客户端使用那些网络函数从操作系统的内部内存拷贝数据至它自己的内存. 如上所示,这里存在两

进程-IPC 共享内存和消息队列 (三)

详见:https://github.com/ZhangzheBJUT/linux/blob/master/IPC(%E4%B8%89).md 五 共享内存 5.1. 共享内存简介 共享内存指多个进程共享同一块物理内存,它只能用于同一台机器上的两个进程之间的通信.在进程的逻辑地址空间中有一段地址范围是用来进行内存映射使用的,该段逻辑地址空间可以映射到共享的物理内存地址上(进程空间介绍:http://blog.csdn.net/zhangzhebjut/article/details/3906025