linux系统中一切皆文件
fd?=?open("led驱动的文件",O_RDWR);
read(fd);
write();
close();
对灯写一个驱动
?led_driver.c
?driver_open();
?driver_read();
?driver_write();??
?driver_close();
struct?file_operations
?{
int?(*open)?(struct?inode?*,?struct?file?*);???
ssize_t?(*read)?(struct?file?*,?char?__user?*,?size_t,?loff_t?*);
ssize_t?(*write)?(struct?file?*,?const?char?__user?*,?size_t,?loff_t?*);???????
int?(*release)?(struct?inode?*,?struct?file?*);//(close)
}
cdev:
设备号1???????????设备号2?????????????设备号n
设备驱动1?????设备驱动2????....??? 设备驱动n
设备号:32位,无符号数字
高12位???:主设备号?:区分哪一类设备
低20位???:次设备号?:区分同类中哪一个设备
每个驱动里面都有对应的file_operations
open打开文件,这个文件与底层的驱动的设备号有关系,
通过设备号访问设备驱动中的struct?file_operations里面的open函数。
open函数会有一个返回值,文件描述符fd,read函数通过fd
找到驱动中的struct?file_operations里面的read函数。
struct?file_operations
?{
int?(*open)?(struct?inode?*,?struct?file?*);???
ssize_t?(*read)?(struct?file?*,?char?__user?*,?size_t,?loff_t?*);
ssize_t?(*write)?(struct?file?*,?const?char?__user?*,?size_t,?loff_t?*);???????
int?(*release)?(struct?inode?*,?struct?file?*);//(close)
}
int register_chrdev(unsigned?int?major, const char *name, const struct?file_operations?*fops)
功能:注册一个字符设备驱动
参数:
@major:主设备号??
??:如果你填写的值大于0,它认为这个就是主设备号
??:如果你填写的值为0,操作系统给你分配一个主设备号
@name :名字 cat?/proc/devices?
@fops :操作方法结构体
返回值:major>0 ,成功返回0,失败返回错误码(负数)?vi?-t?EIO
major=0,成功主设备号,失败返回错误码(负数) ??
当注册一个字符设备驱动的时候。
如果成功的话,当你使用cat?/proc/devices?命令查看的时候可以看到系统自动分配的主设备号和这个名字
void unregister_chrdev(unsigned?int?major, const char *name)
功能:注销一个字符设备驱动
参数:
@major:主设备号
@name:名字
返回值:无
三、手动创建设备文件?mknod
sudo?mknod?led?(路径是任意)?c/b??主设备号???次设备号
sudo?–rf?led?删除的时候记得加-rf
#include?<linux/module.h>
#include?<linux/init.h>
#include?<linux/printk.h>
#include?<linux/fs.h>
#define?NAME?"chrdev_devled"
int?major?= 0; //保存主设备号
//?open?read?write?release?初始化
int myopen(struct inode *node, struct file *file_t)
{
printk("%s?%s?%d\n", __FILE__, __func__, __LINE__);
return 0;
}
ssize_t myread(struct file *file_t, char?__user?*ubuf, size_t?n, loff_t *off_t)
{
printk("%s?%s?%d\n", __FILE__, __func__, __LINE__);
return 0;
}
ssize_t mywrite(struct file *file_t, const char?__user?*ubuf, size_t?n, loff_t *off_t)
{
printk("%s?%s?%d\n", __FILE__, __func__, __LINE__);
return 0;
}
int myclose(struct inode *node, struct file *file_t)
{
printk("%s?%s?%d\n", __FILE__, __func__, __LINE__);
return 0;
}
struct file_operations?fops?= {
.open?=?myopen,
.read?=?myread,
.write?=?mywrite,
.release?=?myclose,
};
//入口函数
static int?__init?chrdev_init(void)
{
printk("%s?%s?%d\n", __FILE__, __func__, __LINE__);
//注册字符设备驱动:?主设备号?驱动名?结构体
????major=register_chrdev(major,?NAME, &fops);
//容错判断
if(major?< 0)
{
printk("chrdev_register?err.\n");
return -EINVAL;
}
return 0;
}
//出口函数
static void?__exit?chrdev_exit(void)
{
printk(KERN_ERR?"%s?%s?%d\n", __FILE__, __func__, __LINE__);
//注销字符设备驱动
unregister_chrdev(major,?NAME);
}
module_init(chrdev_init);//入口
module_exit(chrdev_exit);//出口
MODULE_LICENSE("GPL");//协议
#include?<sys/types.h>
#include?<sys/stat.h>
#include?<fcntl.h>
#include?<unistd.h>
#include?<sys/ioctl.h>
#include?<stdio.h>
int?main(int?argc,char?*argv[])
{
????int?fd?= -1;
????char?buf[32] = "";
if(argc?< 2)
{
????????printf("请输入要打开的文件\n");
return 1;
}
????fd?=?open(argv[1],O_RDWR);
if(fd?< 0)
{
????????printf("open?%s?failed\n",argv[1]);
return 2;
}
????read(fd,buf,sizeof(buf));
????write(fd,buf,sizeof(buf));
????read(fd,buf,sizeof(buf));
????write(fd,buf,sizeof(buf));
????printf("buf=%s\n",buf);
????close(fd);
????fd?= -1;
return 0;
}
--make?驱动文件
--insmod?安装驱动
--cat?/proc/devicse?查看设备号
--sudo?mknod?led?c?244?0?创建设备文件(设备节点)
--dmesg?查看消息
--sudo?dmesg?-C删除消息?
--sudo?gcc?app.c?编译应用层读取文件
--./app?.led读取
--led--dmesg?查看消息