软件开发的家园,编程爱好者的天地.

现在是:北京时间 2016/4/14 上午11:50:51 星期四

设为首页  |  加入收藏  |  网站地图

一个简单的字符驱动程序
发布于:第八基地 来源:duote 作者:天堂路上 时间:2016-04-11 点击:224

  代码分为:makefile ,内核态程序 globalmem.c 用户态程序 user.c 功能是把一个数组排序,你也可以使用 read write函数往内存里写东西。

  运行方法:

  make,产生globalmem.ko文件, Insmod globalmem.ko , 看一下 dmesg -c 是否有提示信息(也可以 lsmod | grep "glo"), 有的话说明加载上了,

  然后 mknod /dev globalmem c 254 0 , 看一下 ls /proc/device/ | grep "glo" 有东西没。

  然后运行用户态程序,数组被排序了。dmesg -c 可以看到提示信息, 在模块中排序了。

  上代码(是带锁的代码,顺便练练手)

  makefile

  1# makefile for kernel 2.6

  2ifneq ($(KERNELRELEASE),)

  3#mymodule-objs := file1.o file2.o

  4obj-m := globalmem.o

  5

  6else

  7PWD := $(shell pwd)

  8KVER := $(shell uname -r)

  9KDIR := /lib/modules/$(KVER)/build

  10all:

  11 $(MAKE) -C $(KDIR) M=$(PWD)

  12clean:

  13 rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions

  14

  15endif

  16

  内核模块

  1#include <linux/module.h>

  2#include <linux/types.h>

  3#include <linux/errno.h>

  4#include <linux/mm.h>

  5#include <linux/sched.h>

  6#include <linux/version.h>

  7#include <linux/cdev.h>

  8#include <asm/io.h>

  9#include <asm/system.h>

  10#include <asm/uaccess.h>

  11#include "mem.h"

  12

  13#define GLOBALMEM_SIZE 0x1000

  14#define MEM_CLEAR 0x1

  15#define ARRAY_INSTER 0x2

  16#define GLOBALMEM_MAJOR 254

  17

  18static int globalmem_major = GLOBALMEM_MAJOR;

  19

  20//the struct of global

  21typedef struct __globalmem_dev{

  22 struct cdev cdev;

  23 unsigned char mem[GLOBALMEM_SIZE];

  24 //add lock, signal

  25 struct semaphore sem;

  26 atomic_t ato;

  27}globalmem_dev;

  28

  29globalmem_dev * global;

  30

  31typedef struct __arithmetic_st{

  32 int buf[10];

  33 int len;

  34}arithmetic_st;

  35

  36

  37

  38

  39int globalmem_open(struct inode *inode, struct file * filp)

  40{

  41 filp->private_data = global;

  42 //you can only open one file

  43 if(!atomic_dec_and_test(&global->ato))

  44 {

  45 printk( KERN_NOTICE "atomic is lock ");

  46 return -EBUSY;

  47 }

  48 return 0;

  49}

  50

  51int globalmem_release(struct inode * inode, struct file * filp)

  52{

  53 atomic_inc(&global->ato);

  54 return 0;

  55}

  56

  57

  58//read

  59static ssize_t globalmem_read(struct file * filp, char __user *buf, size_t size, loff_t *ppos)

  60{

  61 unsigned long p = *ppos;

  62 unsigned int count = size;

  63 int ret = 0;

  64

  65 globalmem_dev *dev = filp->private_data;

  66

  67 if(p > GLOBALMEM_SIZE)

  68 return count ? -ENXIO : 0;

  69 if(count > GLOBALMEM_SIZE - p)

  70 count = GLOBALMEM_SIZE - p;

  71//add the lock

  72 if(down_interruptible(&dev->sem))

  73 {

  74 return -ERESTARTSYS;

  75 }

  76

  77

  78 if(copy_to_user(buf, (void *)(dev->mem + p), count)){

  79 ret = -EFAULT;

  80 }else{

  81 *ppos += count;

  82 ret = count;

  83 printk(KERN_INFO "read %d bytes from %u ", count, p);

  84 }

  85//unlock

  86 up(&dev->sem);

  87 return ret;

  88}

  89

  90//write

  91static ssize_t globalmem_write(struct file * filp, const char __user * buf,

  92 size_t size, loff_t *ppos)

  93{

  94 unsigned long p = *ppos;

  95 unsigned int count = size;

  96 int ret = 0;

  97 globalmem_dev *dev = filp->private_data;

  98

  99 if(p >= GLOBALMEM_SIZE)

  100 return count ? -ENXIO : 0;

  101 if(count > GLOBALMEM_SIZE - p)

  102 count = GLOBALMEM_SIZE - p;

  103//lock

  104 if(down_interruptible(&dev->sem)){

  105 return -ERESTARTSYS;

  106 }

  107 if(copy_from_user((dev->mem + p), buf, count))

  108 ret = -EFAULT;

  109 else{

  110 *ppos += count;

  111 ret = count;

  112 printk( KERN_INFO "written %d bytes from %u ", count , p);

  113 }

  114//unlock

  115 up(&dev->sem);

  116 return ret;

  117}

  118

  119//seek

  120static loff_t globalmem_llseek(struct file * filp, loff_t offset, int orig)

  121{

  122 loff_t ret = 0;

  123 switch(orig){

  124 case 0:

  125 if(offset < 0){

  126 ret = -EINVAL;

  127 break;

  128 }

  129 if((unsigned int) offset > GLOBALMEM_SIZE){

  130 ret = -EINVAL;

  131 break;

  132 }

  133 filp->f_pos = (unsigned int)offset;

  134 ret = filp->f_pos;

  135 break;

  136 case 1:

  137 if((filp->f_pos + offset) > GLOBALMEM_SIZE){

  138 ret = -EINVAL;

  139 break;

  140 }

  141 if((filp->f_pos + offset) < 0){

  142 ret = -EINVAL;

  143 break;

  144 }

  145 filp->f_pos += offset;

  146 ret = filp->f_pos;

  147 break;

  148 default :

  149 ret = -EINVAL;

  150 break;

  151 }

  152 return ret;

  153}

  154static int inster_arithmetic(int * buf, int len)

  155{

  156 int i;

  157 int j;

  158 int key;

  159

  160 if(len < 2){

  161 return -1;

  162 }

  163 for( j = 1; j < len; j++){

  164 key = *(buf + j);

  165 i = j -1;

  166

  167 while(i >= 0 && *(buf + i) > key){

  168 *(buf + i + 1) = *(buf + i);

  169 i = i - 1;

  170 }

  171 *(buf + i + 1) = key;

  172 }

  173}

  174

  175//ioctl

  176static int globalmem_ioctl(struct inode * inode, struct file * filp,

  177 unsigned int cmd, unsigned long arg)

  178{

  179 globalmem_dev * dev = filp->private_data;

  180 arithmetic_st * p;

  181 arithmetic_st * q;

  182 int i;

  183

  184 switch(cmd){

  185 case MEM_CLEAR:

  186 //lock

  187 if(down_interruptible(&dev->sem)){

  188 return -ERESTARTSYS;

  189 }

  190 memset(dev->mem, 0, GLOBALMEM_SIZE);

  191 printk(KERN_INFO "glbalmem is set to zero ! ");

  192 //unlock

  193 up(&dev->sem);

  194 break;

  195 case ARRAY_INSTER:

  196 p = (arithmetic_st *)arg;

  197 q = (arithmetic_st *)kmalloc(sizeof(arithmetic_st), GFP_KERNEL);

  198 memset(q->buf, 0, 10);

  199 if(down_interruptible(&dev->sem)){

  200 return -ERESTARTSYS;

  201 }

  202 if(copy_from_user(q, p, sizeof(arithmetic_st))){

  203 return -EFAULT;

  204 }

  205 if(q->len != 0){

  206 inster_arithmetic(q->buf, q->len);

  207 if(copy_to_user(p, q, sizeof(arithmetic_st))){

  208 return -EFAULT;

  209 }

  210 for(i = 0; i < q->len; i++){

  211 printk(KERN_INFO ">>>>>>>>>>buf%d:%d ! ",i, q->buf[i]);

  212 }

  213 }else{

  214 printk(KERN_INFO ">>>>>>>>>>len is zero [%d] [%s] ! ", __LINE__, __FUNCTION__);

  215 }

  216 kfree(q);

  217 break;

  218

  219 default:

  220 return -EINVAL;

  221 }

  222 return 0;

  223}

  224

  225static const struct file_operations globalmem_fops =

  226{

  227 .owner = THIS_MODULE,

  228 .llseek = globalmem_llseek,

  229 .read = globalmem_read,

  230 .write = globalmem_write,

  231 .ioctl = globalmem_ioctl,

  232 .open = globalmem_open,

  233 .release = globalmem_release,

  234};

  235//register cdev

  236static void globalmem_setup_cdev(globalmem_dev * dev, int index)

  237{

  238 int err;

  239 int devno = MKDEV(globalmem_major, index);

  240

  241 cdev_init(&dev->cdev, &globalmem_fops);

  242 dev->cdev.owner = THIS_MODULE;

  243// dev->cdev.ops = &globalmem_fops;

  244 err = cdev_add(&dev->cdev, devno, 1);

  245 if(err)

  246 printk( KERN_NOTICE "error %d adding LED %d" , err, index);

  247}

  248

  249//

  250int globalmem_init(void)

  251{

  252 int result;

  253 dev_t devno = MKDEV(globalmem_major, 0);

  254

  255 if(globalmem_major){

  256 result = register_chrdev_region(devno, 1, "globalmem");

  257 }else{

  258 result = alloc_chrdev_region(&devno, 0, 1, "globalmem");

  259 globalmem_major = MAJOR(devno);

  260 }

  261 if(result < 0)

  262 return result;

  263 global = kmalloc(sizeof(globalmem_dev), GFP_KERNEL);

  264 if(!global){

  265 result = -ENOMEM;

  266 goto fail_kmalloc;

  267 }

  268 memset(global, 0, sizeof(globalmem_dev));

  269 globalmem_setup_cdev(global, 0);

  270 printk( KERN_NOTICE "init over! ");

  271 //lock

  272 init_MUTEX(&global->sem);

  273 atomic_set(&global->ato, 1);

  274 printk( KERN_NOTICE "init signl! ");

  275 printk( KERN_INFO "the process is %s pid is %i ", current->comm, current->pid);

  276 return 0;

  277

  278fail_kmalloc:

  279 unregister_chrdev_region(devno, 1);

  280 return result;

  281}

  282//

  283void globalmem_exit(void)

  284{

  285 cdev_del(&global->cdev);

  286 kfree(global);

  287 unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);

  288 printk( KERN_NOTICE "exit over! ");

  289}

  290

  291MODULE_AUTHOR("xueby");

  292MODULE_LICENSE("XBY/GPL");

  293module_param(globalmem_major, int , S_IRUGO);

  294

  295module_init(globalmem_init);

  296module_exit(globalmem_exit);

  297

  用户态

  1#include<stdio.h>

  2#include<string.h>

  3#include<stdlib.h>

  4#include<unistd.h>

  5#include<sys/stat.h>

  6#include<fcntl.h>

  7#include<sys/types.h>

  8

  9#define MEM_CLEAR 0x1

  10#define ARRAY_INSTER 0x2

  11

  12typedef struct __arithmetic_st{

  13 int buf[10];

  14 int len;

  15}arithmetic_st;

  16

  17

  18

  19int main()

  20{

  21 int ret;

  22 int fd;

  23 int buf[10] = {2, 5, 1, 9, 3, 12, 0,15, 11, 23};

  24 char rbuf[100] = {0, };

  25 arithmetic_st *a;

  26

  27 a = (arithmetic_st*)malloc(sizeof(arithmetic_st));

  28 if(!a)

  29 return -1;

  30 memcpy(a->buf, buf, sizeof(buf));

  31 a->len = 10;

  32

  33 fd = open("/dev/globalmem", O_RDWR , S_IRWXU);

  34 ioctl(fd, ARRAY_INSTER, (unsigned long)a);

  35 for(ret = 0; ret < 10; ret++){

  36 printf("%d ;",a->buf[ret]);

  37 }

  38 return 0;

  39}

  40

  41

对我有帮助
(0)
0%
对我没帮助
(0)
0%
返回顶部
在线反馈
在线反馈