Linux&Apue(0.0.0):Linux下的I/O文件调用&获取存放的温度数据

Linux下的I/O文件调用&获取存放的温度数据

  • (一)文件和文件描述符
    • (1) 文件扩展名和文件类型
      • 1.1 文件扩展名
      • 1.2 文件类型
    • (2) 文件描述符(file descriptor→fd)
      • 2.1 文件描述符的含义和作用
      • 2.2 通过例子了解文件描述符
  • (2) 文件I/O操作的基本定义和函数
    • 2.1 文件I/O操作的基本定义
    • 2.2文件I/O操作函数
      • 2.2.1 open()系统调用
      • 2.2.2 create()系统调用
      • 2.2.3 close()系统调用
      • 2.2.4 write()系统调用
      • 2.2.5 read()系统调用
      • 2.2.6 lseek()系统调用
      • 2.2.7 dup() 和 dup2()系统调用
      • 2.2.8 stat()和fstat()系统调用
      • 2.2.9 access()系统调用
      • 2.2.10 unlink()系统调用
      • 2.2.11 rename()系统调用
  • (3) 文件I/O操作示例
    • 3.1 C程序读取DS18B20温度源码
      • 3.1.1 main()主函数:打印温度
      • 3.1.2 寻找w1_slave文件
      • 3.1.3 打开w1_slave并读取温度
      • 3.1.4 编译&运行ds18b20

(一)文件和文件描述符

(1) 文件扩展名和文件类型

1.1 文件扩展名

目的:其实在Linux下文件是否可以执行与文件拓展名没有太大关系。但是,我们添加这种扩展名可以进行人为的区分,以便后面的有效分类以及使用。

扩展名 表示 扩展名 表示
.tar, .tar.gz, .tgz, .zip, .tar.bz 表示压缩文件,创建命令为tar, gzip, unzip等 .sh 表示shell脚本文件
.pl 表示perl语言文件 .py 表示python语言文件
.conf 表示系统服务的配置文件 .c 表示C文件
.h 头文件 .cpp 表示C++源文件
.so 表示动态库文件 .a 表示静态库文件

1.2 文件类型

Linux下有7种类型文件(可以通过ls -l命令查看):

文件类型标识 文件类型
- 普通文件
d(dierectory) 目录文件
l (link) 符号链接
c(character) 字符设备
b(block) 块设备
p (pipe) 管道
s(socket) 套接字

(2) 文件描述符(file descriptor→fd)

2.1 文件描述符的含义和作用

文件描述符:内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符(0是标准输入,1是标准输出,2是标准错误)。所有执行I/O操作的系统调用都通过文件描述符。(来源:百度百科)
文件描述符的优点:
基于文件描述符的I/O操作兼容POSIX标准。
在UNIX、Linux的系统调用中,大量的系统调用都是依赖于文件描述符。

文件描述符 用途 POSIX文件描述符 标准I/O文件流
0 标准输入 STDIN_FILENO stdin
1 标准输出 STDOUT_FILENO stdout
2 标准出错 STDERR_FILENO stderr

2.2 通过例子了解文件描述符

例如:现在我想将stdout.c文件中的hello world打印到屏幕上去

#include  			//printf在该头文件中声明
#include  		//STDOUT_FILENO, stdout等在该头文件中声明
#include  		//strlen在该头文件中声明,具体参考man strlen
#define MSG_STR "Hello World\n"

int main(int main, char *argv[])		//argc是命令行总的参数个数,argv[]是argc个参数
{
printf("%s", MSG_STR);
fputs(MSG_STR, stdout);							//fputs→ouput of characters and strings
write(STDOUT_FILENO, MSG_STR, strlen(MSG_STR)); 	//write→send amessage to another user
return 0;
}
gcc stdout.c -o stdout   //转换成可执行文件
./stdout				//执行stdout文件

得到:
在这里插入图片描述
那么fputs和write在这里起什么作用呢?
接下里我们将fput和write的代码段删掉

#include  			//printf在该头文件中声明
#define MSG_STR "Hello World\n"

int main(int main, char *argv[])
{
printf("%s", MSG_STR);
return 0;
}

执行后得到:
在这里插入图片描述
总结:其实我们可以发现printf和fputs和write所表现的功能是一样的,都是“Hello world!"输出到屏幕上。但是,我们发现所用的参数不一样。就像fputs→标准I/O文件流。write→POSIX文件描述符。

(2) 文件I/O操作的基本定义和函数

2.1 文件I/O操作的基本定义

(不带缓存)文件I/O操作:打开文件、读文件、写文件、关闭文件等,对应用到的函数有:open、read、write、close、lseek(文件指针偏移)
不带缓存:每一个函数都只调用系统中的一个函数。
来源:https://www.cnblogs.com/wurenzhong/p/7500867.html

2.2文件I/O操作函数

2.2.1 open()系统调用

open()系统调用:用来打开一个文件,并返回一个文件描述符(file description), 并且该文件描述符是当前进程最小、未使用的文件描述符数值。

int open(const char *path,int oflag,.../*mode_t mode*/);   //路径、输出模式、(文件权限)
参数 功能
path 要打开的文件、设备的路径
oflag 必选:O_RDONLY (只读)、 O_WRONLY(只写)、 O_RDWR(读写)
oflag 常用可选:O_APPEND 每次写时都追加到文件的尾端
oflag 常用可选:O_CREAT 文件不存在则创建它,使用该选项需要第三个参数mode(必须带该参数用来指定创建文件的权限模式)
oflag 常用可选:O_TRUNC 如果文件存在,而且为只写或读写成功打开,则将其长度截取为0;
oflag 常用可选:O_NONBLOCK 如果path是一个FIFO、块设备、字符特殊文件则此选项为文件的本次打开和后续的I/O操作设置非阻塞模式方式。

示例代码:

int fd;
if(fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDWR|O_CREAT|O_TRUNC, 0666)<0); 

返回值:
等于0:若所有欲核查的权限都通过了检查。
小于0:只要有一个权限被禁止。

2.2.2 create()系统调用

create ()系统调用:用来创建一个新文件并返回其fd。

int creat(const char *path, mode_t mode); //路径、权限

示例代码:

fd=creat("....",0666)

2.2.3 close()系统调用

close()系统调用:用来关闭一个打开的文件描述符,会返回fd。

int close (int fd);

2.2.4 write()系统调用

write()系统调用:用来往打开的文件描述符fd指向的文件中写入buf指向的数据,其中nbytes指定要写入的数据大小。

ssize_t write(int fd,const void *buf, size_t nbytes);

返回值(一般与nbytes相同):
大于0:返回nbytes数据大小。
小于0:出错(写操作错误,还有死循环等)。

2.2.5 read()系统调用

read()系统调用:从打开的文件描述符对应的文件中读取数据放到buf指向的内存空间中去。

ssize_t read(int fd, void *buf, size_t nbytes)

返回值:
大于0:返回实际读到的字节数。
小于0:出错。

2.2.6 lseek()系统调用

lseek()系统调用:从文件里读出内容,或往文件写如内容的时候都有一个起始地址,这个起始地址就是当前文件偏移量,当我们对文件
进行读写的时候都会使文件偏移量往后偏移。

off_t lseek(int fd, off_t offset, int whence);
whence 光标位置
SEEK_SET 文件头
SEEK_CUR 当前位置
SEEK_END 文件尾

2.2.7 dup() 和 dup2()系统调用

dup() 和 dup2()系统调用:复制一个新文件描述符来指向fd对应文件。

dup() dup2()
int dup(int fd) int dup2(int fd,int fd2)
返回新文件描述符(最小数值) 可以用fd2参数来指定新文件描述符

dup2用法:
比如1本身没有什么意义,但是我们可以用数字1来映射一种信息。比如说1就代表人,2代表牛,3代表羊。当我们使用dup2后。我现在不让3代表羊了,让3代表人。那么我之前所有和3说话的函数,就不再是和羊说话,而改为和人说话了。同理,1的背后就是stdout,如果我们dup2(fileFd, 1)。那么1的背后就不再是标准输出(指显示器设备),而变为了fileFd背后的文件。我们的printf == fprintf(stdout, …) ,那些所有原来向stdout输出的函数,他们只知道向stdout输出,但stdout的背后被我们修改了,他们是不知道的。简单来说,就是我们修改了映射关系。(转自:网友答复)

2.2.8 stat()和fstat()系统调用

stat()和fstat()系统调用:返回文件/目录的相关信息。

stat() fstat()
int stat(const char * restrict path, struct stat *restrict buf); int fstat(int fd, struct stat *buf);
返回新文件描述符(最小数值) 可以用fd2参数来指定新文件描述符

2.2.9 access()系统调用

access()系统调用:测试文件存在/权限。

int access(const char *path, int mode);    //路径 模式
模式 说明 模式 说明
R_OK 测试读许可权 W_OK 测试写许可权
X_OK 测试执行许可权 F_OK 测试文件是否存在

2.2.10 unlink()系统调用

unlink()系统调用:删除文件(path指定的文件的链接数减1。当链接数为0时,文件内容被删除)。

2.2.11 rename()系统调用

rename()系统调用:文件重命名。

 int rename(const char *oldname, const char *newname);

(3) 文件I/O操作示例

3.1 C程序读取DS18B20温度源码

通过例子了解文件I/O操作
例如:我现在有一个w1_slave文件(放置温度监测的温度读数),现在我想要编写file_io.c文件去读取w1_slave文件里面存放的温度数据。
在这里插入图片描述
t=14500就是现在的温度(当然,真实的温度是14.5°。所以后面编写代码的时候,我们要/1000)。

3.1.1 main()主函数:打印温度

目的:打印温度数据。
Linux&Apue(0.0.0):Linux下的I/O文件调用&获取存放的温度数据_第1张图片

3.1.2 寻找w1_slave文件

因为:在实际工作中,存放w1_slave文件的28-041731f7c0ff文件夹。文件夹名字中的28-后面的序列号会变化,但是28-不会变化。
所以:我们在这里进行了寻找w1_slave文件的操作。
Linux&Apue(0.0.0):Linux下的I/O文件调用&获取存放的温度数据_第2张图片

3.1.3 打开w1_slave并读取温度

Linux&Apue(0.0.0):Linux下的I/O文件调用&获取存放的温度数据_第3张图片

3.1.4 编译&运行ds18b20

gcc ds18b20.c -o ds18b20
./ds18b20

在这里插入图片描述

你可能感兴趣的:(c++,linux)