欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

走近科学之串口设备驱动 --让我很头痛!

程序员文章站 2024-02-22 10:25:40
...

小编开篇一张图,然后开始编!  排版。。。

走近科学之串口设备驱动 --让我很头痛!走近科学之串口设备驱动 --让我很头痛!

大爷的,还玩重载,该打!

走近科学之串口设备驱动 --让我很头痛! 哦哦走近科学之串口设备驱动 --让我很头痛!

不得不吐槽的C嘎嘎,看着都不顺眼,C语言才是最好的编程语言!(表打我!分手失恋中...)

走近科学之串口设备驱动 --让我很头痛!

终端设备上的:

划重点!!!=======================================================================》》

 

Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志

阻塞:https://blog.csdn.net/yikai2009/article/details/8653697

          在设计简单字符驱动程序时,要注意一个重要问题.

          当一个设备无法立刻满足用户的读写请求时应当如何处理?

          例如:调用 read 时没有数据可读,但以后可能会有;

          或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据.

          应用程序通常不关心这种问题,应用程序只是调用 read 或 write 并得到返回值.

          驱动程序应当 ( 缺省地 ) 阻塞进程使它进入睡眠直到请求可以得到满足.

阻塞操作:

          是指在执行设备操作时,若不能获得资源则挂起进程,直到满足可操作的条件后进行操作,

          被挂起的进程进入睡眠状态,被从调度器的运行队列移走,直到等待的条件被满足.

非阻塞操作:

          进程不能进行设备操作时并不挂起,他或者放弃,或者不停的查询,直到可以进行操作为止.

 

阻塞方式-read- 实现:

          在阻塞型驱动程序中,read 实现方式如下:

          如果进程调用 read ,但设备 没有数据 或 数据不足,进程阻塞.

          当新数据到达后,唤醒被阻塞进程.

阻塞方式-write- 实现:

          在阻塞型驱动程序中,write 实现方式如下:

          如果进程调用了 write ,但设备 没有足够的空间供其写入数据,进程阻塞.

          当设备中的数据被读走后,缓冲区中空出部分空间,则唤醒进程.

非阻塞方式的读写操作:

          阻塞方式是文件读写操作的默认方式,但是应用程序员可通过使用O_NONBLOCK 标志来人为

          的设置读写操作为非阻塞方式 .( 该标志定义在 < linux/fcntl.h > 中,在打开文件时指定 ) .

          如果设置了 O_NONBLOCK 标志,read 和 write 的行为是不同的 ,如果进程没有数据就绪时调用了 read ,

          或者在缓冲区没有空间时调用了 write ,系统只是简单的返回 -EAGAIN,而不会阻塞进程.

实例 --- 读阻塞的实现:

          走近科学之串口设备驱动 --让我很头痛!

          走近科学之串口设备驱动 --让我很头痛!

 

用 while 是因为可能别的信号唤醒了睡眠,我们要通过while 重新检测是否真有数据了....

          走近科学之串口设备驱动 --让我很头痛!

 

实例 --- 按键驱动阻塞实现:

1,在 open 函数 查看看是 阻塞方式 还是 非阻塞方式:

         file 结构体中含有 f_flags 标志位,看是 阻塞方式 还是 非阻塞方式:

         O_NONBLOCK 为 非阻塞方式

  1. if (file->f_flags & O_NONBLOCK) /* 非 阻塞操作 */

  2. {

  3. if (down_trylock(&button_lock)) /* 无法获取信号量,down_trylock 立马返回 一个 非零值 */

  4. return -EBUSY;

  5. }

  6. else /* 阻塞操作 */

  7. {

  8. /* 获取信号量 */

  9. down(&button_lock); /* 获取不到 睡眠 */

  10. }

 

2,在 read 函数中同样查看:

 
  1. if (file->f_flags & O_NONBLOCK) /* 非 阻塞操作 */

  2. {

  3. if (!ev_press) /* ev_press 为 1 表示有按键按下,为 0 if 成立 ,没有按键按下, */

  4. return -EAGAIN; /* 返回 -EAGAIN 让再次来执行 */

  5. }

  6. else /* 阻塞操作 */

  7. {

  8. /* 如果没有按键动作, 休眠 */

  9. wait_event_interruptible(button_waitq, ev_press);

  10. }

 

3,应用程序中:

1,以阻塞方式运行:

后台执行应用程序,进程处于睡眠状态,按下按键,立马打印按键号;

 
  1. int main(int argc, char **argv)

  2. {

  3. unsigned char key_val;

  4. int Oflags;

  5.  
  6. fd = open("/dev/buttons", O_RDWR );

  7. if (fd < 0)

  8. {

  9. printf("can't open!\n");

  10. return -1;

  11. }

  12.  
  13. while (1)

  14. {

  15. read(fd, &key_val, 1);

  16. printf("key_val: 0x%x\n", key_val);

  17. }

  18.  
  19. return 0;

  20. }


 

2,以非阻塞方式运行:

open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;

后台执行应用程序:

 
  1. int main(int argc, char **argv)

  2. {

  3. unsigned char key_val;

  4. int ret;

  5. int Oflags;

  6.  
  7. fd = open("/dev/buttons", O_RDWR | O_NONBLOCK);

  8. if (fd < 0)

  9. {

  10. printf("can't open!\n");

  11. return -1;

  12. }

  13.  
  14. while (1)

  15. {

  16. ret = read(fd, &key_val, 1);

  17. printf("key_val: 0x%x, ret = %d\n", key_val, ret);

  18. sleep(5);

  19. }

  20.  
  21. return 0;

  22. }

 

非阻塞方式,没有按键值按下,程序立马返回;
read 返回值 为 -1;

 

 

 

 

文件IO详解(五)---open函数详解

函数原型:https://www.cnblogs.com/frank-yxs/p/5925574.html

走近科学之串口设备驱动 --让我很头痛!

 

函数参数:

  • pathname:打开文件的路径名
  • flags:用来控制打开文件的模式
  • mode:用来设置创建文件的权限(rwx),当flags中带有O_CREAT时才有效。

返回值:

  • 调用成功时返回一个文件描述符fd
  • 调用失败时返回-1,并修改errno

=======================================================

flags参数详解:

  • O_RDONLY:只读模式
  • O_WRONLY:只写模式
  • O_RDWR:可读可写模式

上面三种模式在flags参数中不能同时出现但必须有一种出现,下面的参数是可选的。

  • O_APPEND:以后每次写文件时都会先将当前文件偏移量设置到文件末尾,但是读文件时时不影响的
  • O_CREAT:如果文件不存在则创建
  • O_EXCL:要打开的文件如果存在则出错,必须要和O_CREAT参数一起使用
  • O_TRUNC:打开文件的同时将文件中的内容清除
  • O_NOCTTY:如果打开的文件是终端设备,则不将此设备设置为进程的控制终端
  • O_NONBLOCK:如果打开的文件是一个管道、一个块设备文件或一个字符设备文件,则后续的I/O操作均设置为非阻塞方式
  • O_SYNC:使每次write都等到物理I/O操作完成

========================================================

    open函数返回的文件描述符fd一定是未使用的最小的文件描述符。利用这个特性,可以改变0,1,2这三个文件描述符所指向的文件,由于进程默认会打开0,1,2这三个文件描述符,而且指向了键盘和显示器的设备文件。如果在open之前先进行close(1),然后再调用open函数就会返回最小的未使用的fd,也就是1。

 =======================================================

    如果文件不存在,而且又使用了O_CREAT标志,也就是会创建文件,创建文件时会给文件一定的权限,但是这个权限并不会限制该进程后面对该文件的操作。举个例子,如果创建文件时给的权限是0555,也就是所有用户都没有写的权限。但是程序后面还是可以对文件进行写操作。

=======================================================

    当mode参数是由八进制数字给出的时候,如 0777 .要纠正一个错误,就是之前我认为 权限数字前面的 0 代表的是八进制的含义,其实并不是这样的,前面的 0 代表了权限修饰位,也就是set-user-id位、set-group-id位和sticky这三位的权限。

=======================================================

    creat函数相当于open(pathname,  O_WRONLY | O_CREAT | O_TRUNC, mode),由于open函数完全可以替代creat函数,所以现在基本上不用creat函数了。

 

 

 

 

 

 

 

 

相关标签: 串口 驱动

上一篇: buildroot的图形解析

下一篇: SPI + DMA