对于文件的操作一般有五个函数
open()
read()
write()
ioctl()
close()
也就是说Linux上层应用,对字符类设备调用的时候,就是通过这几个函数来完成的
举个例子:点灯程序
main()
{
int fd,ret;
char *leds = "/dev/leds";
if((fd = open(leds, O_RDWR|O_NOCTTY|O_NDELAY))<0)
printf("open %s failed\n",leds);
else{
ioctl(fd,1,1);
printf("open %s success\n",leds);
}
close(fd)
}
首先用open函数打开LED这个设备,然后用ioctl()对LED进行控制,也就是点亮或熄灭,最后 关掉close()
我们做驱动,尤其是字符类驱动,就是做好open(),write(),ioctrl()等几个函数,然后等着上层去调用!也就是说,所谓做驱动,搞来搞去就是去做那几个函数!
1 Linux底层那么多驱动,有LED,LCD,TP,蜂鸣器,都使用那几个函数,我们怎么能正确找到它呢?
2 另外一个问题,我们做了那几个函数以后,怎么挂接到Linux系统上呢?(也就是说,怎么才能让那几个函数被系统发现呢)
知识点1 设备文件 或者叫 设备节点
在Linux文件系统里面,肯定会有个目录叫做 /dev,目录里的所有文件 是 设备文件,而不是普通的文件,也就是说所有的设备,只要是做好了驱动,都要在这个目录里生成一个文件!
比如我们对LED操作,那就要用 open这个函数打开设备文件 /dev/leds
char *leds = "/dev/leds";
if((fd = open(leds, O_RDWR|O_NOCTTY|O_NDELAY))<0)
设备文件(节点),它就是应用程序和驱动程序之间的桥梁!
设备文件里面什么也没有,但包含了两个信息:主设备号 和 次设备号
主设备号用来区分不同类的设备,比如LED,串口,网络等。。次设备号区分同类设备里的不同的硬件,比如板子有四个串口,这四个串口主设备号相同,次设备号却不相同。
知识点2 如何将做好的函数注册到系统中去
Linux为了解决这个问题,专门做了一个注册函数 register_chrdev(),
int register_chrdev ( unsigned int major , const char *name, struct file_operations*fops);
第一个参数就是 major ,也就是刚才说的主设备号
第二个参数就是 name, 也就是设备文件的 名字
第三个是个结构 file_operations,这个里面就是函数指针,实际就是我们做的那5个函数存在里面!(打开 关闭 读 写 控制)
truct file_operations simple_fops = {
.owner = THIS_MODULE,
.read = LED_read,
.write = LED_write,
.open = LED_open,
.release = LED_release,
};
最后通过函数register_chrdev(),把我们做的那几个函数和 设备文件以及设备号关联起来!
总结:
1 做驱动就是做那几个函数:open read 等等; 这里要注意,实际驱动程序中名字会有变化,比如led_open(),led_read()等,
而这几个函数将来会被上层应用程序使用Linux系统函数open()等来间接调用!
2 设备文件 里面包含 主设备号和次设备号
3 设备文件(节点) 就是 上层应用和底层驱动的桥梁
4 驱动做好以后,要通过register_chrdev()注册到系统,这样那几个函数就和设备文件关联起来了
只要理解, 做驱动就是做那几个函数,然后要把他们注册到系统, 并和设备文件关联
上层应用 通过设备文件 来找到驱动的几个函数,并执行!
1 Linux把所有设备看成文件
2 做驱动就是做那几个函数,例如:led_open(), led_read() 等等
3 设备文件 里面包含 主设备号和次设备号
4 设备文件(节点) 就是 上层应用和底层驱动的桥梁
5 驱动做好以后,要通过register_chrdev()注册到系统,这样那几个函数就和设备文件关联起来了
6 上层应用涌过调用系统函数open, read等,再通过设备文件,间接找到led_open(), led_read()等并执行