引言
继上一篇笔记后,这一篇笔记主要是介绍dup、ioctl、fcntl、mmap,以及错误码处理。
dup&dup2
系统中的文件重定向,实际上就是复制文件的描述符。而dup的作用就是复制这个文件的描述符:
上图是使用dup新生成一个fb也是指向a.txt的文件描述符。
那么dup只能使用在最小未使用的文件描述符中
如果要将文件描述符1不指向屏幕而指向a.txt呢?
使用dup2能够令指定文件描述符指向目标文件描述符。
如图就是:将文件描述符1指向文件描述符3指向的目标。(原理与cp类似)
ioctl
我们以一张图来介绍Ioctl
因为ioctl比较杂,因此更多具体的实例还得详细到实际使用的地方,例如控制LCD屏幕,可以作为LCD提供的头文件来作为参数使用。
详细可以通过Man ioctl
fcntl
fcntl会比ioctl晚出现,那么fcntl会比ioctl的功能整理地更加完善一些。但是与ioctl一样,参数也是需要根据实际需要而定。
但是不一样的是,fcntl有固定的cmd命令集。详细可以man fcntl查看。
cmd | 功能 |
---|---|
F_DUPFD | 功能与dup类似 |
F_DUPFD_CLOEXEC | 多进程时,打开新文件代码是否被继承 |
F_GETFD | 获得/设置fd标签(很少用) |
F_SETFL | 打开文件的模式设定(只读,只写,可读可写,阻塞方式打开等) |
F_SETLK | 文件锁 |
mmap
一般使用在特殊文件处理。这里以LCD显示器为例:
- 第一步:每个硬件设备在Linux中dev目录下的设备节点文件,那么首先将这个设备节点文件与内存进行映射。
- 这里以LCD为例,长宽比为800:480,那么这块内存的大小主要取决于LCD屏幕的字节数,假设一个像素点为4字节,那么这块内存的大小就为:4800480字节。
- 那么mmap函数就充当这个过程的映射作用。
- 如果我们要将一张图片显示在LCD上,只需要将图片放入内存中就可以直接映射在LCD屏幕上。
代码实现
void *mmap(void * addr, size_t length, int prot ,
int flags ,int fd ,off_t offset);
参数 | 作用 |
---|---|
addr | 映射内存的起始地址,一般设置为NULL就会自动寻找一个合适的起始地址 |
length | 映射内存的大小,可以比显示屏大,但是不建议比显示屏小。 |
prot | 映射内存的保护权限: |
prot | PROT_EXEC:可执行 |
prot | PROT_READ:可读 |
prot | PROT_WRITE:可写 |
prot | PROT_NONE:不可访问 |
flags | 当多个进程同时访问该内存时,该参数可以决定某一个进程内使映射内存的数据发生变更是否影响其他进程,也可以决定是否影响其对应的文件数据 |
fd | LCD的文件描述符 |
offset | 图像偏移量相对的偏移 |
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
#include<linux/input.h>
#include<sys/stat.h>
#include<sys/types.h>
#include <sys/mman.h>
#define BLACK 0xFFFFFFFF
#define WRITE 0x00000000
#define BLUE 0x000000FF
int main(int argc, char const *argv[])
{
int lcd = open("/dev/fb0", O_RDWR|O_EXCL);
char *p_lcd;
p_lcd = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
unsigned x = BLACK;
int i ;
for ( i = 0; i < 800*480; i++)
{
memcpy(p_lcd+(4*i),&x,4);
}
return 0;
}
错误码处理
在编写代码的过程中,可以使用错误码处理,有针对显示出错误信息。
首先需要包含一个头文件errno.h
,那么在使用我们的IO函数的过程是这样的:
- 例如open函数是首先在应用中开始工作,然后进入库函数,完成工作后,再返回给应用。
- 可是当在运行过程中遇到错误,比如权限不足,就会把信息发送给errno,errno会输出一个错误码。
- 那么问题来了,errno只是负责输出一个错误码,而我们并不看得懂这个错误码,因此就要使用函数:perror或者strerror 函数来解读这个错误码:
perror("XXXX") perror会将XXXX完整输入,
并且在后面自动加上错误信息
strerror(errno) 会将errno给的错误码进行解读,
然后返回一个字符串