linux IO 知识点

嵌入式系统分为三层  应用层(C、java、数据结构和算法、Android等)再往为内核层(linux高级编程,学好这部分才能利用linux 系统做事情)再往下为硬件层(和之前搞单片机的那套系统差不多了)。

linux高级编程:其实就对linux内核向用户空间提供的许多函数或接口的学习。即函数功能、参数、返回值。

 IO知识点:IO针对的是应用层与内核层的间输入与输出。

注:linux命令都是由linux内核函数接⼝所编写的程序来实现的。

文件IO:

注: 文件描述符?内核采用ID号的形式标识一个文件。那么文件ID号在每个用户的程序中怎么映射的呢?就是文件描述符。

当一个程序开始运行时,它一般会有3个已经打开的文件描述符,就是

0:标准输入

1:标准输出

2:标准错误

那些数学(即0、1、2)就是文件描述符,因为在Linux上一切都是文件,所以标准输入(stdin),标准输出(stdout)和标准错误(stderr)也可看作文件来对待。

 

open()的返回值就是这个ID号。文件权限标识:

参    数

说    明

参    数

说    明

S_IRUSR

所有者拥有

读权限

S_IXGRP

群组拥有执

行权限

S_IWUSR

所有者拥有

写权限

S_IROTH

其他用户拥

有读权限

S_IXUSR

所有者拥有

执行权限

S_IWOTH

其他用户拥

有写权限

S_IRGRP

群组拥有读权限

S_IXOTH

其他用户拥

有执行权限

S_IWGRP

群组拥有写权限

 

 

文件权限标志也可以使用加权数字表示,这组数字被称为umask变量,它的类型是mode_t,是一个无符号八进制数。umask变量的定义方法如表13.4所示。umask变量由3位数字组成,数字的每一位代表一类权限。用户所获得的权限是加权数值的总和。例如764表示所有者拥有读、写和执行权限,群组拥有读和写权限,其他用户拥有读权限。设置的值mode      &         ~(取反) umask(系统值),这样才得出我们设置的文件真正的权限值,或者将umask设置为0

表13.4  umask变量表示方法

加 权 数 值

1

2

3

4

所有者拥有

读权限

群组拥有读权限

其他用户拥

有读权限

2

所有者拥有

写权限

群组拥有写权限

其他用户拥

有写权限

1

所有者拥有

执行权限

群组拥有执行权限

其他用户拥

有执行权限

 

 

标准IO:

与文件IO的不同?

文件IO是直接调用内核提供的接口函数,头文件是unistd.h

标准IO是调用C语言的库函数的方式间接调用内核的系统函数,头文件是stdio.h

提供三种缓冲

1.全缓冲:在缓冲区写满时输出到指定的输出端. 比如对磁盘上的文件进行读写通常是全缓冲的.
2.行缓冲:在遇到'\n'时输出到指定的输出端. 比如标准输入和标准输出就是行缓冲, 回车后就会进行相应的I/O操作.
3.无缓冲:有什么就输出什么. 比如标准错误输出, 出错时立即显示出来.stderr就是了。
设置缓冲方式的函数有两个,分别为setbuf,setvbuf
可用fflush立即输出,不管缓冲区是否达到输出标准

 

打开、关闭

定义在/usr/include/libio.h

1.FILE *fopen(const char *restrict pathname, const char *restrict type)
第一个参数为文件的路径,
第二个参数为打开的方式: r/rb只读; w/wb只写; a/ab添加; r+/ra+读写; w+/wa+读写; a+/ab+文件尾添加读写

a:追加 

w:会重新创建一个

+读写

b:打开二进制文件

2.int fclose(FILE *fp)成功返回 0,失败返回EOF=-1,
关闭打开的文件流, 释放缓存;在文件被关闭前会刷新(将缓存中的数据放到内核调用的硬件上面去)缓存。

行缓存读写函数,即遇到"\n"或写满时会调用系统函数

fgets/fputs

scanf/printf
gets/puts默认对应终端窗口的输入输出

注意: puts会在行尾插入添加一个'\n', 所以当我们用puts打印文件时,每行显示时都有两个'\n'(除最后一行外), 也就是每行内容下面都会有一个空行

注:

char * fgets(char *s,int size,FILE *stream);

第一个参数:读到哪里去

第二个参数:读多少个字节

第三个参数:从哪里读   成功返回s(缓存的地址),若已经到文件结尾或失败返回null

 

int fputs(const char *s,FILE *stream);

第一个参数:缓存,写什么内容

第二个参数:写到哪里去

成功为非负值,失败返回EOF -1.

 

刷新缓存函数 fflush(FILE *fp)把缓存中的数据强制写到内核中。

无缓存:标准出错流stderr

调整读写位置函数:

fseek()参数与lseek()参数是一样的,不同的是返回值

lseek返回当前文件位置

fseek返回0,失败返回-1

rewind(FILE *fp)文件的位置为开始相当于(void )fseek(fp,0 SEEK_SET);

ftell()取得当前文件的位置指针
 

另一对行缓存读写函数 gets()和puts()

char *gets(char *s)//只从标准的输入读,同时也没有缓存的大小,存在越界的可能有BUG

与fgets 不同:gets并不将新行符存入缓存

int puts(const char *s)//只能写到标准的输出

与fputs不同:puts在输出的时候会添加一个\n

 

另一对比较常用的读写函数 printf sprintf fprint

int fprintf(FILE *stream,“字符串格式");//可以输出到文件也可以输出到显示器printf只能输出到显示器

int sprintf(str *,“字符串格式”);//输出格式内容到字符串中;把要写的东西写到一个字符串中。

一个字符的读写函数

int fgetc(FILE *fp)//从文件中读取一个字符

参数:文件流

返回:正确为读取的字符,到文件结尾或出错返回EOF

int fputc(int c,FILE *fp)//写一个字符到文件中

参数:第一个参数为要写的字符,第二个参数为文件流

返回:正确返回输入的字符,出错返回EOF

如何区分是到文件尾还是读写出错??

int feof(FILE *stream)//判断是否到文件结尾

参数:文件流

返回值:到文件结尾返回为非0,没有则返回0.

int ferror(FILE *stream)//判断是否读写错误

参数:文件流

返回值:是读写错误,返回为非0,不是则返回0

void clearerr(FILE *stream)//清除流错误

参数为:文件流

全缓存读写函数

size_t fread(void *put,size_t size,size_t nmemb,FILE *stream);

size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);

第一个参数buf ;写的内容

第四个参数stream 写到哪里去

第二个参数:size;写的内容中,每一个单元所占的字节数

第三个参数:nmemb:写的内容中,有多少个单元数。

总共写多少个字节,=size *nmemb

返回值:实际读写单元数


linux静态库和动态库(共享库)的制作

静态库以libXX.a结尾,编译时就加载到程序中。

动态库以libXX.so结尾,动行时将库加载到可执行程序中,运行环境必须提供相应的外部库。

 

静态库的制作:

1、生成目标文件:gcc -c file.c

2、静态函数库创建命令 ar

ar  -cr lib file.a file.o

 -c :create的意思 

-r : replace的意思,表示当插入的模块file.o已经存在libfile.a中,则覆盖,反之ar显示一个错误消息。

使用:gcc XX.c -L. -lxx     //注:XX指要编译的c文件 xx是静态库文件名 -l已经指明是静态库,所以直接加文件名就可以

不用再加.a

删除.a文件后,main依然可以运行,因为静态库内容已经整合进去了 

 

动态库的制作:

1、生成目标文件:gcc -c file.c

2、gcc -shared -fpic -o libfile.so file.o

-fpic: 产生位置无关代码

-shared: 生成共享库

 使用:gcc -o out main.c  -L. -lfile

此时还不能立即./out,因为在动态函娄库使用时,默认会查找usr/lib 目录下的动态函数库

第一种方法:

将libaddsu.so放到usr/lib或.lib中去。

第二种方法:假设libfile.so在/home/linux/file相当于windows下环境变量的设置

exprot LD_LIBRARY_PATH=/hom/linux/addsub  //代表当前.so所在的路径。 $LD_LIBRARY_PATH

第三种方法:

在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/$bin/ldconfig

/etc/ld.so.conf是非常重要的目录,存放着是链接咕咕和加载器搜索共享库时要检查的目录,默认是从/usr/lib/ 或/lib中读取的,所以可以把库目录加入到这个文件中执行。

目录IO:对目录进行操作

#include <sys/types.h>

#include <dirent.h>

1、创建目录

int mkdir(const char *path,mode_t mode)

path为欲创建的目录的文件路径

mode为该目录的访问权限

成功则返加0,失败返回-1。

生成的目录权限仍和unmask有关系。

 

opendir

DIR *opendir(const char *pathname);//打开目录及路径

返回值:成功返回目录流指针,出错返回NULL

readdir 

struct dirent  *readdir(DIR *dr)//目录流指针

成功为struct dirent指针,若在目录尾或出错返回NULL

struct dirent 定义在头文件dirent.h中

struct dirent

{

ino_td ino://inode号

char d_name[NAME_MAX+1];//文件名

}

2、rewinddir:重置读取目录的位置为开头

void rewinddir(DIR *dr)

参数:目录流指针

 

long relldir(DIR *dirp)

参数:目录流指针

返回目录流当前位置

 

void seekdir(DIR *dirp,long loc)//类似于文件定位函数fseek(),在目录流上设置下一个readdir()操作的位置

参数:目录流指针和偏移量

 

4、closedir

int closedir(DIR *dr)

参数:目录流指针

成功返回0,出错返回-1

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值