创建字符设备的三种方法

将创建字符设备的三种方法记录一下,以便以后参考.
1. 使用早期的register_chardev()方法
 
   
#include < linux / kernel.h >
#include
< linux / module.h >
#include
< linux / fs.h >
#include
< asm / uaccess.h >
int init_module( void );
void cleanup_module( void );
static int device_open( struct inode * , struct file * );
static int device_release( struct inode * , struct file * );
static ssize_t device_read( struct file * , char * , size_t, loff_t * );
static ssize_t device_write( struct file * , const char * , size_t, loff_t * );
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80
static int major;
static int Device_open = 0 ;
static char msg[BUF_LEN];
static char * msg_ptr;
static struct file_operations fops =
{
.read
= device_read,
.write
= device_write,
.open
= device_open,
.release
= device_release,
};
int init_module( void )
{
major
= register_chrdev( 0 , DEVICE_NAME, & fops);
if (major < 0 )
{
printk(KERN_ALERT
" Registering char device failed with %d\n " , major);
return major;
}
printk(KERN_INFO
" I was assigned major number %d.\n " , major);
return SUCCESS;
}
void cleanup_module( void )
{
int ret = unregister_chrdev(major, DEVICE_NAME);
if (ret < 0 )
{
printk(KERN_ALERT
" Error in unregister chrdev %d\n " , major);
}
}
static int device_open( struct inode * inode, struct file * file)
{
static int counter = 0 ;
if (Device_open)
{
return - EBUSY;
}
Device_open
++ ;
sprintf(msg,
" I already told you %d times hello world\nDevice_open=%d\n " ,
counter ++ , Device_open);
msg_ptr
= msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release( struct inode * inode, struct file * file)
{
Device_open
-- ;
module_put(THIS_MODULE);
return 0 ;
}
static ssize_t device_read( struct file * filp, char * buffer, size_t length, loff_t * offset)
{
int bytes_read = 0 ;
if ( * msg_ptr == ' \0 ' )
return 0 ;
printk(KERN_ALERT
" length=%d\n " , length);
while (length && * msg_ptr)
{
put_user(
* (msg_ptr ++ ), buffer ++ );
length
-- ;
bytes_read
++ ;
}
return bytes_read;
}
static ssize_t device_write( struct file * filp, const char * buff, size_t len, loff_t * off)
{
printk(KERN_ALERT
" Sorry, this operation isn't supported\n " );
return - EINVAL;
}

2. 使用cdev的方法
 
   
#include < linux / kernel.h >
#include
< linux / module.h >
#include
< linux / fs.h >
#include
< linux / types.h >
#include
< linux / fs.h >
#include
< linux / cdev.h >
#include
< asm / uaccess.h >
int init_module( void );
void cleanup_module( void );
static int device_open( struct inode * , struct file * );
static int device_release( struct inode * , struct file * );
static ssize_t device_read( struct file * , char * , size_t, loff_t * );
static ssize_t device_write( struct file * , const char * , size_t, loff_t * );
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80

static int major;
static int Device_open = 0 ;
static char msg[BUF_LEN];
static char * msg_ptr;
static struct cdev * my_cdev;
static struct file_operations fops =
{
.read
= device_read,
.write
= device_write,
.open
= device_open,
.release
= device_release,
};
int init_module( void )
{
int err;
dev_t devid ;
alloc_chrdev_region(
& devid, 0 , 1 , " chardev " );
major
= MAJOR(devid);
my_cdev
= cdev_alloc();
cdev_init(my_cdev,
& fops);
err
= cdev_add(my_cdev, devid, 1 );
if (err)
{
printk(KERN_INFO
" I was assigned major number %d.\n " , major);
return - 1 ;
}
printk(
" major number is %d\n " , MAJOR(devid));
return SUCCESS;
}
void cleanup_module( void )
{
cdev_del(my_cdev);
printk(
" cleanup done\n " );
}
static int device_open( struct inode * inode, struct file * file)
{
static int counter = 0 ;
if (Device_open)
{
return - EBUSY;
}
Device_open
++ ;
sprintf(msg,
" I already told you %d times hello world\nDevice_open=%d\n " ,
counter ++ , Device_open);
msg_ptr
= msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release( struct inode * inode, struct file * file)
{
Device_open
-- ;
module_put(THIS_MODULE);
return 0 ;
}
static ssize_t device_read( struct file * filp, char * buffer, size_t length, loff_t * offset)
{
int bytes_read = 0 ;
if ( * msg_ptr == ' \0 ' )
return 0 ;
printk(KERN_ALERT
" length=%d\n " , length);
while (length && * msg_ptr)
{
put_user(
* (msg_ptr ++ ), buffer ++ );
length
-- ;
bytes_read
++ ;
}
return bytes_read;
}
static ssize_t device_write( struct file * filp, const char * buff, size_t len, loff_t * off)
{
printk(KERN_ALERT
" Sorry, this operation isn't supported\n " );
return - EINVAL;
}
3. 使用udev在/dev/下动态生成设备文件的方式
 
   
#include < linux / kernel.h >
#include
< linux / module.h >
#include
< linux / types.h >
#include
< linux / fs.h >
#include
< linux / cdev.h >
#include
< linux / pci.h >
#include
< linux / moduleparam.h >
#include
< linux / init.h >
#include
< linux / string .h >
#include
< asm / uaccess.h >
#include
< asm / unistd.h >
#include
< asm / uaccess.h >
MODULE_LICENSE(
" GPL " ); /* 此处如果不加的话加载的时候会出错 */
int init_module( void );
void cleanup_module( void );
static int device_open( struct inode * , struct file * );
static int device_release( struct inode * , struct file * );
static ssize_t device_read( struct file * , char * , size_t, loff_t * );
static ssize_t device_write( struct file * , const char * , size_t, loff_t * );
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80

static int major;
static int Device_open = 0 ;
static char msg[BUF_LEN];
static char * msg_ptr;
static struct cdev * my_cdev;
static struct class * my_class;
dev_t devid ;
static struct file_operations fops =
{
.read
= device_read,
.write
= device_write,
.open
= device_open,
.release
= device_release,
};
int init_module( void )
{
int err;
alloc_chrdev_region(
& devid, 0 , 1 , " chardev " );
major
= MAJOR(devid);
my_cdev
= cdev_alloc();
cdev_init(my_cdev,
& fops);
my_cdev
-> owner = THIS_MODULE;
err
= cdev_add(my_cdev, devid, 1 );
if (err)
{
printk(KERN_INFO
" I was assigned major number %d.\n " , major);
return - 1 ;
}
my_class
= class_create(THIS_MODULE, " chardev_class1 " );
if (IS_ERR(my_class))
{
printk(KERN_INFO
" create class error\n " );
return - 1 ;
}
class_device_create(my_class, NULL, devid, NULL,
" chardev " " %d " , MINOR(devid));
printk(
" major number is %d\n " , MAJOR(devid));
return SUCCESS;
}
void cleanup_module( void )
{
cdev_del(my_cdev);
class_device_destroy(my_class, devid);
class_destroy(my_class);
printk(
" cleanup done\n " );
}
static int device_open( struct inode * inode, struct file * file)
{
static int counter = 0 ;
if (Device_open)
{
return - EBUSY;
}
Device_open
++ ;
sprintf(msg,
" I already told you %d times hello world\nDevice_open=%d\n " ,
counter ++ , Device_open);
msg_ptr
= msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release( struct inode * inode, struct file * file)
{
Device_open
-- ;
module_put(THIS_MODULE);
return 0 ;
}
static ssize_t device_read( struct file * filp, char * buffer, size_t length, loff_t * offset)
{
int bytes_read = 0 ;
if ( * msg_ptr == ' \0 ' )
return 0 ;
printk(KERN_ALERT
" length=%d\n " , length);
while (length && * msg_ptr)
{
put_user(
* (msg_ptr ++ ), buffer ++ );
length
-- ;
bytes_read
++ ;
}
return bytes_read;
}
static ssize_t device_write( struct file * filp, const char * buff, size_t len, loff_t * off)
{
printk(KERN_ALERT
" Sorry, this operation isn't supported\n " );
return - EINVAL;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值