学完了基础知识,开始正式linux的学习了,在一般的招聘中linux有应用层开发和底层驱动开发等,他们之间都是相互联系的。从上到下,从全局到局部的方法能够更好的进行理解。
应用层掉用c库,然后c库通过统一接口(系统调用)与内核进行交互,内核中有加载着字符设备驱动,块设备驱动等,从上到下的机构从图中能够较为清晰的看出来。
下面开始应用层开发的基础,标准IO,也就是标准的输入输出。
linux中 一切皆文件,对文件的操作肯定是最基本且重要的。
1.文件的概念及文件类型
1.1 文件:一组相关数据的有序集合。我们在windos中经常认为一个文本一个word是文件,在linux中文件表示的范围更大。
1.2 常见的文件类型及代表字母
记住这些字母,在平时的查找中就知道都是些什么类型的文件了。
常规文件 |
r |
目录文件 |
d
|
字符设备文件 |
c
|
块设备文件 |
b
|
管道文件
|
p |
套接字文件 |
s
|
符号链接文件 |
l |
1.标准IO介绍
1.1 标准I/O由ANSI C标准定义
1.2 标准I/O通过缓冲机制减少系统调用,实现更高的效率。
1.3 标准I/O所有操作都是围绕FILE来进行,FILE又称为流
1.3.1流的缓冲类型:
全缓冲:当流的缓冲区无数据或者无空间才执行I/O操作。
行缓冲:遇到’\n’,操作(我们终端操作的时候都是这种stdin stdout)
无缓冲:直接写入文件,不缓冲(标准出错,确保实时性 stderr)
1.3.2 标准IO预定义流:
当我们提到标准I/O时u,基本上人们都会说到:标准输入,标准输出,标准出错。
嗯,标准I/O预定义3个流,程序运行时自动打开。
2.文件的打开和关闭
在对文件的操作的前提下,肯定是先能够对文件打开关闭,这个其实也简单,记住函数传入的参数有哪些,什么情况下用什么参数就可以了(区分参数的区别)。
2.1打开流:
FILE *fopen (const char *path, const char *mode); 成功返回流指针,出错返回NULL
2.2关闭流:
int fclose(FILE *stream);成功返回0,失败返回EOF,并设置errno
其实还算好记,r,r+,w,w+,a,a+.
r就是读的缩写,就是只读呗,但是要有文件,没有读个啥。
r+,读写,它加的是写,但是看字面也知道他也得有文件
w呢就是写,既然是写,我们是主动的,没有就创建呗,但是我写就是从头写。
w+,加上的是读。
a这个看字母就比较特殊表示只写,不存在就写,写是跟在末尾,低调了很多啊。
a+,就是多了个读。
是不是很好记啦,不过记不住也没事,他无非就是个API记不住通过man fopen也能查看他的使用方法。
注:fopen 创建的文件访问权限是0666(rw-rw-rw-)
这个访问权限受linux umask的影响。
3.标准错误的输出函数:(之后调试经常使用)
void perror(const char *s); perror先输出字符串s,再输出错误号对应的错误信息
char *strerror(int errno); errno 存放错误号,由系统生成,r根据错误号返回对应的错误信息。
4.字符的输入输出
在学习新的函数之前,我们之前在c基础中也学过一些字符的输入输出函数。
putchar() getchar() printf() scanf() gets() puts();
下面学的输入输出,感觉就是这些函数的升级板,用法上和上面都差不多。
4.1读一个字符: int fgetc(FILE *stream); 成功返回读取字符,失败返回EOF
4.2写一个字符:int fputc(int c, FILE *stream); 成功返回写入字符,失败返回EOF
4.3读一行:char *fgets(char *s, int size, FILE *stream); 成功返回S,出错返回NULL(size-1个)
4.4写一行:int fputs(const char *s, FILE *stream); 成功返回字符个数,出错返回EOF(不追加\n)
4.5读写若干个对象:
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
成功返回读写的对象个数;出错时返回EOF
既可以读写文本文件,也可以读写数据文件
例:
int s[10];
if (fread(s, sizeof(int), 10, fp) < 0) {
perror(“fread”);
return -1;
}
struct student {
int no;
char name[8];
float score;
} s[] = {{ 1, “zhang”, 97}, {2, “wang”, 95}};
fwrite(s, sizeof(struct student), 2, fp);
4.6格式化输入输出:
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
5.流的刷新:
int fflush(FILE *fp);
成功返回0,错误返回EOF,将流缓冲区中的数据写入实际的文件(没有满也没有遇到回车,但是现在就想将缓冲区的数据存到文件中去)
linux下只能刷新输出缓冲区,输入缓冲区丢弃。
6.定位流:
long ftell(FILE *stream); 文件流当前的读写位置,成功时返回流的当前读写位置,出错时返回EOF
long fseek(FILE *stream, long offset, int whence); 定位流指针到任意位置,定位一个流,成功时返回0,出错时返回EOF,whence参数:SEEK_SET/SEEK_CUR/SEEK_END,offset参数:偏移量,可正可负
void rewind(FILE *stream);将流定位到文件开始位置
7.流是否出错或结束
int ferror(FILE *stream);返回1表示流出错;否则返回0
int feof(FILE *stream);返回1表示文件已到末尾;否则返回0