1.1.什么是应用编程
(1)典型的嵌入式产品就是基于linux系统来工作的。典型的嵌入式产品研发过程为:第1步是让linux系统在硬件上跑起来(系统移植工作);第2步是基于linux系统来开发应用程序实现产品功能。
(2)基于linux去做应用编程,其实就是通过调用linux的系统API来实现应用需要完成的任务。
1.2.操作系统API和文件IO接口
(1)API是一些函数,这些函数由linux系统提供支持,由应用程序来使用。应用层程序通过调用API来调用操作系统中的各种功能,实现具体的任务。学习一个操作系统,其实就是学习使用这个操作系统的API。
(2)IO就是input/output,输入/输出。文件IO的的意思就是读写文件。
(3)linux系统中常用的文件IO接口函数:open、close、write、read、lseek。
1.3.文件操作的一般步骤
(1)在linux系统中要操作文件,一般是先open打开文件,得到文件描述符,然后对文件进行读写操作(或其它操作),最后close关闭文件即可。
(2)我们对文件进行操作时,一定要先打开文件,打开成功后才能去操作,如果打开失败,后面就无法操作了; 最后读写完成后一定要close关闭文件,否则可能会造成文件损坏。
(3)文件平时是存放在块设备中的文件系统中的,这种文件称为静态文件。当我们使用open打开文件时,linux内核做的操作包括:内核在进程中建立了打开该文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内存中特定地址管理存放,这种文件称为动态文件。
(4)当打开文件后,我们针对该文件的所有读写操作,都是针对内存中存放的动态文件的;当我们对动态文件进行读写后,此时内存中的动态文件和块设备中的静态文件就不同步了;当我们close关闭动态文件时,close内部内核会将内存中的动态文件的内容同步到块设备中的静态文件。
(5)内核设计文件操作的原理:因为块设备本身以块为单位进行读写操作的特性就决定了内核对块设备进行操作非常不灵活;而内存可以按字节为单位进行操作,并且可随机操作,非常灵活。
1.4.文件描述符
(1)文件描述的实质是一个数字,该数字在某个进程中表示某个特定的含义,当我们open打开文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,该数字就和内存中维护这个动态文件的数据结构挂钩绑定了,以后应用程序如果要操作这个动态文件,只需使用该文件描述符进行区分即可。
(2)文件描述符就是用来区分一个程序打开的多个文件的;文件描述符的作用域就是当前进程,出了当前进程该文件描述符就木有意义了。
1.5.打开文件和关闭文件
(1)linux中的文件描述符fd的合法范围是0或者一个正整数,不可能是一个负数。
(2)open返回的fd必须保存好,以后对该文件的所有操作都要靠该fd去对应该文件,最后关闭文件时也需要fd去指定关闭该文件。如果在该文件关闭前丢掉了fd,那么该文件就无法读写和关闭了。
1.6.实时查询man手册
(1)当我们编写应用程序时,很多API原型都不可能记得,所以要实时查询man手册。
(2)man 1 xx查shell命令,man 2 xx查API,man 3 xx查库函数。
1.7.读取文件内容
(1)ssize_t read(int fd, void *buf, size_t count);
fd表示要读取哪个文件,fd一般由前面的open返回得到。
buf是应用程序自己提供的一段内存缓冲区,用来存储读出的内容。
count是我们想要读取的字节数。
返回值表示实际成功读取的字节数。
(2)返回值ssize_t类型是linux内核用typedef重定义的一个类型,其实就是int。其目的是为了构建平台无法代码,方便程序迁移平台,使代码具有更好的可移植性。
1.8.向文件写入
(1)写入用write系统调用,write的原型和理解方法和read相似。
(2)注意const在buf前面的作用是该参数buf是作为输入型参数,输入型参数在函数中是只读的,不能更改。
(3)注意buf的指针类型为void空类型,即该函数操作的数据流没有明确的类型,可操作所有类型的数据。
(4)该示例程序中刚才成功写入14字节,然后读出结果读出是0(但是读出成功了),可考虑该问题的原因是啥。
1.file_open
/*
* 公司:XXXX
* 作者:Rston
* 博客:http://blog.csdn.net/rston
* GitHub:https://github.com/rston
* 项目:文件操作的主要接口API
* 功能:一个简单的文件读写实例。
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv)
{
int fd = -1; // fd即file descriptor,文件描述符
int ret = -1; // 用于接收read返回值,判断是否读文件成功
char buf[100] = {0}; // 构建缓冲区存放从文件读出的内容
char bufwrite[20] = "linux is great"; // 构建缓冲区存放要写入文件的内容
fd = open("test.txt", O_RDWR); // 打开test.txt文件
if (-1 == fd) // 判断文件打开是否成功,也可这样写if (fd < 0)
{
printf("open file error.\n");
}
else
{
printf("open file sucess. fd = %d.\n", fd);
}
ret = write(fd, bufwrite, strlen(bufwrite)); // 写内容到文件中
if (ret < 0) // 判断内容是否成功写入文件
{
printf("write file errot.\n");
}
else
{
printf("write %d bytes to file.\n", ret);
printf("the content of write is [%s].\n", bufwrite);
}
ret = read(fd, buf, sizeof(buf)); // 读取文件内容
if (ret < 0) // 判断读取文件是否成功
{
printf("read file error.\n");
}
else
{
printf("read %d bytes actual from file.\n", ret);
printf("the content of read is [%s].\n", buf);
}
close(fd); // 关闭文件
return 0;
}