memdev.h
#ifndef _MEMDEV_H #define _MEMDEV_H #define MEM_MAGIC 'm' #define MEM_RESTART _IO(MEM_MAGIC, 0)//使用内核提供的宏产生命令, #define MEM_SET _IOW(MEM_MAGIC, 1, int)//改命令向内核传递一个整形的参数 #endif
驱动程序memdev.c
#include <linux/module.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/fs.h> #include <asm/uaccess.h> #include "memdev.h" struct cdev mdev; dev_t devno; static long mem_ioctl(struct file* filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case MEM_RESTART: printk("memdev restart.\n"); break; case MEM_SET: printk("arg is %ld\n", arg);//将用户传递下来的参数打印出来看是否一致 break; default: return -EINVAL; break; } return 0; } struct file_operations memfops = { .llseek = mem_lseek, .unlocked_ioctl = mem_ioctl,//在2.6.36之前内核中为ioctl,2.6.36之后为unlocked_ioctl,函数参数也有变化 }; static __init int memdev_init(void) { cdev_init(&mdev, &memfops); alloc_chrdev_region(&devno, 0, 2, "memdev"); cdev_add(&mdev, devno, 2); printk("memdev_init success\n"); return 0; } static void __exit memdev_exit(void) { cdev_del(&mdev); unregister_chrdev_region(devno, 2); printk("memdev_exit success\n"); } module_init(memdev_init); module_exit(memdev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("liuwei"); MODULE_DESCRIPTION("char driver");
应用程序mem_read.c
#include <stdio.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "memdev.h" int main(int argc, char *argv[]) { int fd = open("/dev/memdev", O_RDWR); if (fd == -1) { perror("open"); return -1; } ioctl(fd, MEM_RESTART);//发送两个控制命令,一个不带参数,一个带一个整形的参数 ioctl(fd, MEM_SET, 10); close(fd); return 0; }驱动程序中动态分配设备号,通过cat /proc/devices 查看系统为memdev分配的设备号。
使用命令mknod /dev/memdev c 252 0创建设备节点。其中252系统分配的设备号。
驱动简单的Makefile
ifeq ($(KERNELRELEASE),) PWD := $(shell pwd) KERNELDIR ?= /home/farsight/samba/linux-2.6.36 INSTALLDIR ?= /nfs/rootnfs/ modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules install: cp *.ko /nfs/rootnfs/ clean: rm -rf *.o *.ko *.mod.c .*.cmd modules.order Module.symvers .tmp_versions else obj-m := memdev.o endif