博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
创建字符设备的三种方法
阅读量:6111 次
发布时间:2019-06-21

本文共 7249 字,大约阅读时间需要 24 分钟。

将创建字符设备的三种方法记录一下,以便以后参考.
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;
}

转载地址:http://pwkka.baihongyu.com/

你可能感兴趣的文章
Oracle 冷备份
查看>>
jq漂亮实用的select,select选中后,显示对应内容
查看>>
C 函数sscanf()的用法
查看>>
python模块之hashlib: md5和sha算法
查看>>
linux系统安装的引导镜像制作流程分享
查看>>
解决ros建***能登录不能访问内网远程桌面的问题
查看>>
pfsense锁住自己
查看>>
vsftpd 相关总结
查看>>
bash complete -C command
查看>>
解决zabbix 3.0中1151端口不能运行问题
查看>>
售前工程师的成长---一个老员工的经验之谈
查看>>
Get到的优秀博客网址
查看>>
dubbo
查看>>
【Git入门之四】操作项目
查看>>
老男孩教育每日一题-第107天-简述你对***的理解,常见的有哪几种?
查看>>
Python学习--time
查看>>
在OSCHINA上的第一篇博文,以后好好学习吧
查看>>
高利率时代的结局,任重道远,前途叵测
查看>>
Debian 6.05安装后乱码
查看>>
欢迎大家观看本人录制的51CTO精彩视频课程!
查看>>