标准IO -> buf -> 文件IO ->磁盘
Linux中对终端进行的IO操作上升到文件IO层有缓存。
终端是行缓存,文件输出是全缓存,实时刷新需要加fflush()
Linux中行缓存 1024字节 全缓存 4096字节
可以通过setvbuf函数改变 //setvbuf(stdout , buf ,_IOLBF,1023)//将标准输出的缓存改为1023的行缓存
查看代码的方法
1. ctags -R ->tags文件
2.vim -t FILE //FILE是查找的关键字段
3.ctrl + ] 进入特定定义
4.Ctrl + t返回
errno:记录出错信息(数字表示)
strerror:将errno的出错号转换为字符串
perror(“。。。”):直接打印出错信息
FILE *fopen(const char *path ,const char *mode)
成功返回FILE指针,失败返回空
int fclose(FILE *stream)
成功返回0,失败返回EOF
读写流结束的判断:
1、feof。一般情况多读一个字符EOF
2、EOF。文件结束或错误返回EOF,用int变量接收
3、ferror,判断文件是否因错误退出
一次读一个字符
int getc(FILE *stream)
int fgetc(FILE *stream)
int getchar (void) // =getc(stdin)
一次写一个字符
int putc(int FILE *stream)
int fputc(int c,FILE *stream)
int putchar(int c)
****以上函数均是文件结尾或出错返回EOF*****
输入一行
char *gets(char *s) //不安全
char *fgets(char *s,int size,FILE *stream) //文件结尾或失败返回NULL
输出一行
int puts(const char *s)//会多添加一个新行符
int fputs(const char *s,FILE *stream) //成功非负,失败EOF
按块读写
size_t fread(void *ptr , size_t size ,size_t nmemb,FILE*stream)
读写到的块数,数组指针,每块的大小,需要读写块数,文件流
size_t fwrite(const *ptr,size_t size ,size_t nmemb,FILE *stream)
文件定位
int fseek(FILE *stream,long offset,int whence)//定位文件指针
long ftell(FILE* stream)//获取当前文件指针位置
void rewind(FILE *stream)//设定文件指针到开始位置
int fgetpos(FILE *stream,fpos_t *pos)//获取文件位置//在系统移植中最好使用这两个函数
int fsetpos(FILE *stream , fpos_t *pos)//设置文件指针位置
临时文件
char* tmpnam(char *s)
FILE *tmpfile(void)
文件IO:
文件描述符:0~1023之间的可用的最小非负整数//一般在文件IO中用,标准IO中一般用文件流
int open(const char *patnname,int flags)
int open(const char *pathname,int flags,mode_t mode)
int creat(const char *pathname,mode_t mode)
int close(int fildes);
ssize_t read(int fd,void *buf,size_t count);//成功返回读到的字节数,0表述文件尾,-1表示出错
ssize_t fwrite(int fd,void *buf,size_t count)
off_t lseek(int fildes,off_t offset ,int whence)//与fseek不同,返回当前文件指针
目录操作
DIR *dirp = opendir("path");
struct dirent *readir(DIR *dirp)//struct dirent *dirent = readir(dirp);
获取文件/目录的属性信息//成功返回0,出错返回-1
1. int stat(const char *filename struct stat *buf)
int fstat(int fildes,struct stat *buf)
int lstat(const char *filename,struct stat *buf)
stat结构体包括 st_dev, st_ino, st_mode, st_nlink, st_uid, st_gid, st_rdev, st_size, st_blksize, st_blocks, st_atime, st_mtime, st_ctime
其中st_mode 成员需要解析,每一位都有不同的含义,包括文件的类型,以及对每个用户的读写权限
而st_*time 则是time_t类型的即从1970年至今的秒数//获取当前时间的函数为time();调用localtime()可将其转换为当地时间,并转成struct tm 类型,注意年份和月份的范围
struct passwd *getpwuid(uid_t uid)//将uid序号转换成对用的用户名
struct group *getgrgid(gid_t gid)//将gid序号转换成对用的组名
mode_t umask(mode_t mask)创建屏蔽字
int truncate(const char *pathname,off_t length)
int ftruncate(int fd,off_t length)//文件阶段
int link(const char *path1,const char *path2)//path2->path1 //建立硬链接
int symlink(const char *path1,const char *path2)//建立符号链接
int unlink(const char *path)//取消链接,可删除文件
int remove(const char *path)//删除指定路径的文件
int rename (const char *old,const char *new)//重命名
创建静态库用ar指令,他将很多.o 转换成 .a
# ar crs libmyhello.a hello.o //规则:以lib为前缀,紧跟静态链接库名,扩展名为 .a
使用静态链接库:
# gcc -o hello main.c -L. -lmyhello //-L path 告诉编译器库位置为path,-l 需链接的库名字 ,-I path 用户头文件路径 //默认为-lc(标准C库)
用gcc创建共享库(动态库)
# gcc -fPIC -Wall -c hello.c //-fPIC 表示编译为位置独立的代码,用于编译共享库
# gcc -share -o libmyhello.so hello.o
使用动态链接库
# gcc main.c -o main -L. -lmyhello -I. //注意库名没有前缀和扩展
readelf -a a.out |grep shared
ldd a.out // 查看可执行文件用到了那些库
让程序顺利找到库的方法
1、将库拷贝到/usr/lib和/lib目录下
2、在LD_LIBRARY_PATH环境变量中加上库的所在路径
3、添加/etc/ld.so.conf.d/*.conf文件,把库的所在路径加到文件末尾,并执行ldconfig刷新
分析命令行参数
getopt(int argc,char *const argv[],const char *optstring )
函数说明 getopt()用来分析命令行参数。参数argc和argv是由main()传递的参数个数和内容。参数 optstring为选项字符串, 告知 getopt()可以处理哪个选项以及哪个选项需要参数,如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。如果在处理期间遇到了不符合optstring指定的其他选项getopt()将显示一个错误消息,并将全域变量optopt设为“?”字符,如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。