一:有的欧洲国家语言用的字母比26个多,占用了ASCII码表中&和其它符号的位置,所以规定了一些操作符的特殊表示方法。
C++中有些用的二联符和三联符
??= 表示 # ??) 表示] ??( 表示[
??! 表示 | ??/ 表示\ ??- 表示~
??> 表示 } ??< 表示( ??' 表示^
<% 表示 { and 表示&& and_eq 表示&=
%> 表示 } bitor 表示| or_eq 表示|=
<: 表示 [ or 表示|| xor_eq 表示^=
:> 表示 ] xor 表示^ not 表示!
%: 表示 # compl 表示~ not_eq 表示!=
%:%:表示 ## bitand 表示&
二:Linux的轮询操作;Linux在驱动层提供了一种非常聪明的方法,就是在驱动层的file_operation中实现poll方法。 poll方法由操作系统每隔一段时间调用一次,当poll 返回1时, 表示可以操作;
使用非阻塞的I/O 的应用程序通常会使用select () 和 poll ()实现轮询操作。 用于查询设备的状态。
三:Linux设备驱动之内存分配与I/O 访问
几乎每一种外设都通过读写设备上的寄存器来控制或数据操作; 外设寄存器也称为 I/O端口; 通常包括控制寄存器, 状态寄存器, 数据寄存器 3大类;CPU对外设I/O进行编址有两种方式: I/O映射方式, 内存映射方式; arm9处理器只实现了一个屋里地址空间,而CPU将外设的I/O 物理地址映射到CPU的单一物理地址空间,因此成为内存的一部分,这是CPU就像访问内存一样访问外设的I/O 端口,这就是所谓的内存映射方式;
Linux中,我们将基于I/O映射方式的或基于内存映射方式的I/O端口成为 I/O 区域, 也就是我们所说的 I/O资源;
当编写的程序在CPU中运行时就成为一个系统进程,会涉及到5种不同的数据段;代码段;数据段,就是存放程序静态分配非变量和全局变量;BSS段,BSS段包含程序中卫初始化的全局变量,BSS段在内存中全部置零;堆,存放进程运行中被动态分配的内存段;栈,是用户存放程序临时创建的局部变量;
四:操作I/O内存
1、申请I/O内存,必须先非配,在<linux/ioport.h>中定义, request_mem_region()函数分配一个开始于start 的len字节的i/o内存区;成功返回非null;
struct resource *request_men_region(unsigned long start, unsigned long len, char *name);
2、映射,在访问i/o内存之前,分配i/o内存并不是唯一要求的步骤,还必须保证内核可存取该i/o 内存; ioremap()函数将i/o内存区映射到虚拟地址;参数phys_addr为要映射到i/o内存起始地址,size为要映射的i/o大小;
void *ioremap(unsigned long phys_addr, unsigned long size);
3、方位i/o内存;ioremap返回的地址不可以直接解引用,应当使用内核提供的访问函数,在<asm/io.h>文件中,I/O内存读函数的参数addr 应该是从ioremap获得的地址(可能包含一个偏移地址),返回值是从给定的I/O 内存读取到的值;
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);
I/O内存写函数,参数addr同I/O内存读函数,参数value为要写的值;
void iowrite8(u8 value, void *addr);
void iowrite16(u16 value, void *addr);
void iowrite32(u32 value, void *addr);
以下这些函数将一系列值读取或写到一个给定的I/O内存地址,从给定的buf读或写 count个值到给定的addr。
void ioread8_rep(void *addr, void *buf, unsigned long count);
void ioread16_rep(void *addr, void *buf, unsigned long count);
void ioread32_rep(void *addr, void *buf, unsigned long count);
void iowrite8_rep(void *addr, const void *buf, unsigned long count);
void iowrite16_rep(void *addr, const void *buf, unsigned long count);
void iowrite32_rep(void *addr, const void *buf, unsigned long count);
需要操作一块I/O地址时,课使用夏磊函数
void memset_io(void *addr, u8 value, unsigned int count);
void memcpy_fromio(void *dest, void *source, unsigned int count);
void memcpy_toio(void *dest, void *source, unsigned int count);
4、释放I/O内存步骤
void iounmap(void *addr);
void release_mem_region(unsigned long start, unsigned long len);
不管是I/O内存还是I/O端口,Linux2.6版本内核提供了一个ioport_map函数;重新映射count个 I/O端口,使他们看起来像I/O内存,驱动在ioport_map返回的地址上使用ioread8和同类函数;