linux chrdev字符设备驱动程序示例

简介

下面代码是一个linux内核模块,用于实现一个简单的字符设备驱动程序示例。示例代码实现了一个简单的字符设备驱动程序,可以读取和写入内核缓冲区中的数据。

代码说明

头文件包含该代码包含了一些Linux内核头文件,这些头文件提供了与Linux内核功能和API相关的定义和声明。

前面的代码段定义了一些用于内核模块的全局变量,包括一个表示设备打开次数的变量和一个用于存储数据的缓冲区。

simple_open()函数和simple_release()函数分别用于处理设备的打开和释放操作。在simple_open()函数中,会检查设备是否已经被打开,若已经打开则返回错误码。在simple_release()函数中,会将设备打开次数减1。

simple_read()函数和simple_write()函数分别用于处理从设备读取数据和向设备写入数据的操作。在simple_read()函数中,会将数据从内核空间拷贝到应用程序空间。在simple_write()函数中,会将数据从应用程序空间拷贝到内核空间。

代码定义了一个struct file_operations结构体变量simple_fops,用于指定文件操作的回调函数。这些回调函数会在对设备进行读、写、打开、释放等操作时被调用。

simple_init_module()函数通过调用register_chrdev()函数来注册字符设备,设备号为simple_MAJOR。simple_cleanup_module()函数用于注销字符设备,并在终端打印一条消息。

 代码


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>

#include "demo.h"

MODULE_AUTHOR("fgj");
MODULE_LICENSE("Dual BSD/GPL");

static unsigned char simple_inc=0;
static unsigned char demoBuffer[256];

int simple_open(struct inode *inode, struct file *filp)
{
	if(simple_inc>0)return -ERESTARTSYS;
	simple_inc++;
	return 0;
}

int simple_release(struct inode *inode, struct file *filp)
{
	simple_inc--;
	return 0;
}

ssize_t simple_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
	/* 把数据拷贝到应用程序空间 */
	if (copy_to_user(buf,demoBuffer,count))
	{
	   count=-EFAULT; 
	}
	return count;
}

ssize_t simple_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
	/* 把数据拷贝到内核空间 */
	if (copy_from_user(demoBuffer+*f_pos, buf, count))
	{
		count = -EFAULT;
	}
	return count;
}

struct file_operations simple_fops = {
	.owner =    THIS_MODULE,
	.read =     simple_read,
	.write =    simple_write,
	.open =     simple_open,
	.release =  simple_release,
};

/*******************************************************
                MODULE ROUTINE
*******************************************************/
void simple_cleanup_module(void)
{
    unregister_chrdev(simple_MAJOR,  "simple"); 
	printk("simple_cleanup_module!\n");
}

int simple_init_module(void)
{
	int ret;
	ret = register_chrdev(simple_MAJOR, "simple", &simple_fops);//注册设备号231,设备名 
	if (ret < 0)
	{
		printk("Unable to register character device %d!\n",simple_MAJOR);
		return ret;
	}
	return 0;
}

module_init(simple_init_module);
module_exit(simple_cleanup_module);

头文件

#ifndef _simple_H_
#define _simple_H_

#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */

/********************************************************
 * Macros to help debugging
 ********************************************************/
#undef PDEBUG             /* undef it, just in case */
#ifdef simple_DEBUG
#ifdef __KERNEL__
#    define PDEBUG(fmt, args...) printk( KERN_DEBUG "DEMO: " fmt, ## args)
#else//usr space
#    define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
#endif
#else
#  define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif

#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */

//设备号
#define simple_MAJOR 224

//设备结构
struct simple_dev 
{
	struct cdev cdev;	  /* Char device structure		*/
};

//函数申明
ssize_t simple_read(struct file *filp, char __user *buf, size_t count,
                   loff_t *f_pos);
ssize_t simple_write(struct file *filp, const char __user *buf, size_t count,
                    loff_t *f_pos);
loff_t  simple_llseek(struct file *filp, loff_t off, int whence);
int     simple_ioctl(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long arg);


#endif /* _simple_H_ */

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的字符设备驱动程序示例代码: ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #define DEVICE_NAME "my_char_dev" #define BUFFER_SIZE 1024 static int major; static char buffer[BUFFER_SIZE]; static ssize_t my_char_dev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { ssize_t retval = 0; if (*f_pos >= BUFFER_SIZE) { goto out; } if (*f_pos + count > BUFFER_SIZE) { count = BUFFER_SIZE - *f_pos; } if (copy_to_user(buf, buffer + *f_pos, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; out: return retval; } static ssize_t my_char_dev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { ssize_t retval = 0; if (*f_pos >= BUFFER_SIZE) { goto out; } if (*f_pos + count > BUFFER_SIZE) { count = BUFFER_SIZE - *f_pos; } if (copy_from_user(buffer + *f_pos, buf, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; out: return retval; } static struct file_operations my_char_dev_fops = { .owner = THIS_MODULE, .read = my_char_dev_read, .write = my_char_dev_write, }; static int __init my_char_dev_init(void) { int retval; memset(buffer, 0, BUFFER_SIZE); major = register_chrdev(0, DEVICE_NAME, &my_char_dev_fops); if (major < 0) { printk(KERN_ERR "Failed to register char device.\n"); return major; } printk(KERN_INFO "Registered char device with major number %d.\n", major); return 0; } static void __exit my_char_dev_exit(void) { unregister_chrdev(major, DEVICE_NAME); printk(KERN_INFO "Unregistered char device with major number %d.\n", major); } module_init(my_char_dev_init); module_exit(my_char_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your name"); MODULE_DESCRIPTION("A simple character device driver."); ``` 这个驱动程序只是一个非常简单的示例,它创建了一个名为 "my_char_dev" 的字符设备,具有读和写功能。当应用程序读取设备时,它从缓冲区中读取数据,并将其复制到应用程序的缓冲区中。当应用程序写入设备时,它将数据从应用程序的缓冲区中复制到驱动程序的缓冲区中。 当你编译并加载这个模块后,在终端中执行命令: ``` $ sudo mknod /dev/my_char_dev c <major number> 0 ``` 其中,`<major number>` 是上面注册的字符设备的主设备号。 然后,你就可以像操作一个普通的文件一样进行读写操作了,例如: ``` $ echo "Hello, world!" > /dev/my_char_dev $ cat /dev/my_char_dev Hello, world! ``` 当然,这个示例只是一个非常简单的驱动程序,实际的驱动程序可能涉及到更复杂的操作,例如设备的初始化,中断处理等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值