嵌入式学习DAY18 --- 文件IO,库

嵌入式入门学习笔记,遇到的问题以及心得体会!
DAY18

笔记:
day2.
>文件IO
>库

文件IO
>文件描述符:
文件描述符是文件IO操作文件的对象
是一个大于等于0的整数

特殊的文件描述符:
0:stdin
1:stdout
2:stderr

>函数:
	打开文件:
		open:
			/*调用时需要添加的头文件*/
			#include <sys/types.h>
	      	#include <sys/stat.h>
	        #include <fcntl.h>
	        /*
	         *函数名:open
	         *函数功能:打开一个文件
	         *函数参数:
	         *			const char *pathname:带路径的文件名
	         *			int flags:打开方式
	         *				O_RDONLY:只读
	         *				O_WRONLY:只写
	         *				O_RDWR:可读可写
	         *函数返回值:int:成功返回一个被打开文件的文件描述符,失败返回一个负数
	         */
	        int open(const char *pathname, int flags);


	创建文件:
		open:
			/*
		         *函数名:open
		         *函数功能:打开文件,如果文件不存在,可以创建(一般用于创建文件)
		         *函数参数:
		         *			const char *pathname:带路径的文件名
		         *			int flags:打开方式
		         *				O_RDONLY:只读
		         *				O_WRONLY:只写
		         *				O_RDWR:可读可写
		         *				O_CREAT:创建时必须加
		         *			mode_t mode:三个八进制的数 0664
		         *函数返回值:成功返回一个被打开文件的文件描述符,失败返回一个负数
		         */
		        int open(const char *pathname, int flags, mode_t mode);

		        不常用的flags:
		        	O_APPEND	如果文件存在,则以追加方式打开
		        	O_TRUNC		如果文件存在,则清空   
		        	O_NOCTTY	如果路径名指向终端设备,不要把这个设备用作控制终端。
		        	O_NONBLOCK	如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)

		        	以下三个常量同样是选用的,它们用于同步输入输出
					O_DSYNC        等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。
					O_RSYNC        read 等待所有写入同一区域的写操作完成后再进行
					O_SYNC         等待物理 I/O 结束后再 write,包括更新文件属性的 I/O

		    标准IO中 r r+ w w+ a a+  分别对应那些 O_XXX 的组合

			标准IO 		文件IO
			r			O_RDONLY
			r+			O_RDWR
			w			O_WRONLY | O_CREAT | O_TRUNC
			w+			O_RDWR   | O_CREAT | O_TRUNC
			a			O_WRONLY | O_CREAT | O_APPEND
			a+			O_RDWR   | O_CREAT | O_APPEND

		open时,文件权限的问题:
			我们在使用0777权限创建文件时,创建出的文件权限是0775,这是为什么?
			因为dest_mode = open_mode & (~umask)

			umask:linux操作系统默认为0002
			故:
				open_mode:0777
				umask:0002

				111 111 111
				000 000 010 按位取反	111 111 101

				按位与的结果:111 111 101	----------->0775
	读文件:
		read:
			/*需要包含的头文件*/
			#include <unistd.h>
			/*
			 *函数名:read
			 *函数功能:从一个文件描述符读取数据
			 *函数参数:
			 *	int fd:被读的文件的文件描述符
			 *	void *buf:buf是用来存储读取数据存储的内存空间的首地址
			 *	size_t count:表示的是想要读取的字节数
			 *函数返回值:int:成功返回读到的字节数,失败返回-1,如果读指针本身就在文件末尾则读不到数据,返回0
			 */
	       	ssize_t read(int fd, void *buf, size_t count);

读文件示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	if(argc != 2)
	{
		puts("Usage:./a.out filename");
		return -1;
	}

	//open file
	int fd = -1;
	fd = open(argv[1], O_RDONLY);
	if(fd < 0)
	{
		puts("open file error.");
		return -1;
	}
	//read file
	char buf[11] = {0};
	int ret = read(fd,buf,sizeof(buf));
	if(ret > 0)
	{
		puts(buf);
		printf("ret:%d\n",ret);
	}
	//close file
	close(fd);
	return 0;
}

	写文件:
		write:
			/*需要包含的头文件*/
			#include <unistd.h>
			/*
			 *函数名:write
			 *函数功能:往一个文件描述符写入数据
			 *函数参数:
			 *	int fd:被写入的文件的文件描述符
			 *	void *buf:buf是用来存储写入数据存储的内存空间的首地址
			 *	size_t count:表示的是想要写入的字节数
			 *函数返回值:int:成功返回写入的字节数,失败返回-1
			 */
	       	ssize_t write(int fd, const void *buf, size_t count);
	关闭文件:
		close:
			/*需要包含的头文件*/
			#include <unistd.h>
			/*
		     *函数名:close
		     *函数功能:关闭一个文件描述符
		     *函数参数:
		     *	int fd:被关闭/想要关闭的文件的文件描述符
		     *函数返回值:int:成功返回0,失败返回-1
		     */
       		int close(int fd);

写文件示例:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main()
{
	//create file
	int fd = -1;
	fd = open("mytest",O_WRONLY | O_CREAT, 0664);
	if(fd < 0)
	{
		puts("creat file error.");
		return -1;
	}
	//write buf to file
	char buf[] = "Tom and Jerry\n";
	write(fd,buf,strlen(buf));
	//close file
	close(fd);
	return 0;
}

	文件重定位:
		lseek:
			/*需要添加的头文件*/
			#include <sys/types.h>
		    #include <unistd.h>
		    /*
		     *函数名:lseek
		     *函数功能:文件读写指针的重定位
		     *函数参数:
		     *			int fd:文件描述符
		     *			off_t offset:偏移量
		     *			int whence:基准
		     *函数返回值:
		     *			off_t:成功返回基于当前位置移动的字节数
		     */
		    off_t lseek(int fd, off_t offset, int whence);

		    whence:
		    	SEEK_SET(文件开头)
		              The offset is set to offset bytes.

		       	SEEK_CUR(当前位置)
		              The offset is set to its current location plus offset bytes.

		       	SEEK_END(文件末尾)
		              The offset is set to the size of the file plus offset bytes.

课堂练习:
1.求文件长度
使用文件IO实现

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	if(argc != 2)
	{
		puts("Usage:./a.out filename");
		return -1;
	}

	int fd = open(argv[1],O_RDONLY);
	if(fd < 0)
	{
		puts("open file error.");
		return -1;
	}
	int ret = lseek(fd,0,SEEK_END);
	printf("ret:%d\n",ret);
	close(fd);
	return 0;
}

库:
->什么是库
库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。
->什么时候使用库
1.工程中部分源代码闭源时使用库
2.版本升级时使用

->库的分类
	静态库:在程序编译时的链接阶段将目标文件.o和库文件.a链接生成可执行文件。将这个过程中的.a称之为静态库
		以.a/.lib为后缀
	动态库:在程序运行时,将加载到内存中的.so代码链接到可执行文件中,执行库中的代码段。将这个过程中的.so称之为动态库。
		以.so/.dll为后缀
		动态库也称之为共享库

	系统 			静态库 			动态库
	Linux下的库 		xxx.a 			xxx.so
	Windows下的库 	xxx.lib 		xxx.dll

->库的制作
	静态库的制作:
		1.将接口文件,编译,汇编生成.o目标文件
			gcc -c xxx.c
		2.使用ar命令,将.o目标文件做成静态库
			ar -crv libxxx.a xxx.o

	动态库的制作:
		创建动态库(.so)
			编写代码
			(老版本的编译器是可以的)
			将代表生成目标文件,此时要加上编译器选项-fPIC
			-fPIC创建与地址无关的编译程序(pic, position independent code),是为了能够在多个应用程序间共享。
			gcc -fPIC -c mysort.c
			然后生成动态库,此时要加链接器选项-shared
			gcc -shared -o libmysort.so mysort.o
			-shared指定生成动态链接库。

			新版本的编译器建议使用如下方法:
				gcc -fPIC -shared -c xxxx.c -o libxxx.so

			注意:建议使用新版的生成方法,新版本向下兼容,旧版本不向上兼容

->库的链接
	静态库的链接:
		1.从指定路径中链接
			gcc xxx.o -L库所在的路径 库名
		2.从环境变量路径中链接
			gcc xxx.o -l库名(-l和库名之间没有空格,库名没有lib前缀和.a后缀)
			例子:
				gcc main.o -lmyreaddir

	动态库链接:
		1.gcc xxx.c -L路径 -l库名
		2.从环境变量路径中链接
			gcc xxx.o -l库名(-l和库名之间没有空格,库名没有lib前缀和.a后缀)
			例子:
				gcc main.o -lmyreaddir

什么是链接:
二进制可执行文件的拼接,称之为重定向或链接。

支持/能够重定向的文件称之为可重定向文件(ELF)文件
	在C语言中,目标文件(.o)和可执行文件(EXE)文件都是可重定向文件。
			  .a 和 .so文件也是可重定向文件

Linux中查看可重定向文件的命令为:readelf 
	例如: readelf -a a.out

动态库和静态库的区别:
纬度 | 静态库 |动态库
------------------------------------------
链接的时间 | 编译时链接 | 运行时链接
------------------------------------------
共享性 | 不具备共享性 | 具备共享性
------------------------------------------
生成的可执行文件| 较大 | 较小
------------------------------------------
版本升级 | 需要重新编译工程| 不需要重新编译工程
不适合升级频繁的 | 适合频繁升级的项目
项目
-------------------------------------------------
可移植性| 方便移植 | 移植较为复杂
-------------------------------------------------

main函数传参:
格式
int main(int argc, char *argv[])
{
return 0;
}
参数的含义:
int argc:命令行参数的个数,包含命令本身
char *argv[]:
argv是一个数组,数组成员个数为argc
数组每一个成员的类型为char *
每一个元素是每一个参数的首地址
参数是字符串类型

char *的含义:
	1.char类型变量的地址
		char c = 5;
		char *p = &c;

	2.char类型数组的首地址
		如果给操作范围了

	3.字符串首地址
		char *p,使用p进行运算了,且没有给操作范围

int arr[5]中arr的含义:
	1.arr代表整个数组,是什么类型 int [5]
		sizeof(arr) = 20

	2.数组的首地址
		类型:int *
		操作数组时,一定有操作范围

	3.int类型数组的第一个元素的地址
		int *: &arr[0]

	arr[0] == *(arr + 0)
	&arr[0] == arr+0
	&arr[0] == arr

作业:
1.自己实现一个cp命令
./a.out srcfile destfile
要求可以拷贝图片
2.实现图片的加密和解密

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值