📄 dev.c
字号:
#ifndef __KERNEL__# define __KERNEL__ //按内核模块编译#endif#ifndef MODULE# define MODULE //设备驱动程序模块编译#endif#define DEVICE_NAME "MyDev" #define OPENSPK 1#define CLOSESPK 2 //必要的头文件#include <linux/module.h> /*同kernel.h,最基本的内核模块头文件*/#include <linux/kernel.h> //同module.h,最基本的内核模块头文件#include <linux/sched.h> //这里包含了进行正确性检查的宏#include <linux/fs.h> //文件系统所必需的头文件#include <asm/uaccess.h> //这里包含了内核空间与用户空间进行数据交换时的函数宏#include <asm/io.h> //I/O访问int my_major=0; //主设备号static int Device_Open=0;static char Message[]="This is from device driver";char *Message_Ptr;int my_open(struct inode *inode, struct file *file){//每当应用程序用open打开设备时,此函数被调用 printk ("\ndevice_open(%p,%p)\n", inode, file); if (Device_Open) return -EBUSY; //同时只能由一个应用程序打开 Device_Open++; MOD_INC_USE_COUNT; //设备打开期间禁止卸载 return 0;}static void my_release(struct inode *inode, struct file *file){//每当应用程序用close关闭设备时,此函数被调用 printk ("\ndevice_release(%p,%p)\n", inode, file); Device_Open --; MOD_DEC_USE_COUNT; //引用计数减1}ssize_t my_read (struct file *f,char *buf,int size,loff_t off){//每当应用程序用read访问设备时,此函数被调用 int bytes_read=0; #ifdef DEBUG printk("\nmy_read is called. User buffer is %p,size is %d\n",buf,size);#endifif (verify_area(VERIFY_WRITE,buf,size)==-EFAULT) return -EFAULT; Message_Ptr=Message; while(size && *Message_Ptr) { if(put_user(*(Message_Ptr++),buf++)) //写数据到用户空间 return -EINVAL; size --; bytes_read++; } return bytes_read; }ssize_t my_write (struct file *f,const char *buf, int size,loff_t off){//每当应用程序用write访问设备时,此函数被调用 int i; unsigned char uc;#ifdef DEBUG printk("\nmy_write is called. User buffer is %p,size is %d\n",buf,size);#endifif (verify_area(VERIFY_WRITE,buf,size)==-EFAULT) return -EFAULT; printk("\nData below is from user program:\n"); for (i=0;i<size;i++) if(!get_user(uc,buf++)) //从用户空间读数据 printk("%02x ",uc); return size; }int my_ioctl(struct inode *inod,struct file *f,unsigned int arg1,unsigned int arg2){//每当应用程序用ioctl访问设备时,此函数被调用#ifdef DEBUG printk("\nmy_ioctl is called. Parameter is %p,size is %d\n",arg1);#endif switch (arg1){ case OPENSPK: printk("\nNow,open PC's speaker.\n"); outb(inb(0x61)|3,0x61); //打开计算机的扬声器 break; case CLOSESPK: printk("\nNow,close PC's speaker."); outb(inb(0x61)&0xfc,0x61);//关闭计算机的扬声器 break;}} struct file_operations my_fops = { NULL, /* lseek */ my_read, my_write, NULL, NULL, my_ioctl, NULL, my_open, my_release, /* nothing more, fill with NULLs */};int init_module(void){//每当装配设备驱动程序时,系统自动调用此函数 int result; result = register_chrdev(my_major,DEVICE_NAME,&my_fops); if (result < 0) return result; if (my_major == 0) my_major = result; printk("\nRegister Ok. major-number=%d\n",result); return 0;}void cleanup_module(void){//每当卸载设备驱动程序时,系统自动调用此函数 printk("\nunload\n"); unregister_chrdev(my_major, DEVICE_NAME);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -