库函数与系统调用嗯的区别在于系统调用能够让你直接访问linux内核提供的丰富服务,比如基于文件描述符的I/O操作。可以把系统调用看作是内核的低级借口。库调用处于linux的编程接口中较高的层次。实际上,许多库函数都是用系统调用来实现的,例如内存分配历程malloc就是由系统调用sbrk实现的。
第二个关键区别就是:系统调用存在于内核空间,而大多数库调用都是用户模式的历程。

1 打开和关闭文件
FILE *标识出一个文件指针

fopen freopen fclose
#include<stdio.h>
FILE *fopen(const char *path,const char *mode);
FILE *fdopen(int fildes,const char *mode);
FILE *freopen(const char *path,const char *mode,FILE *stream);
int fclose(FILE *stream);

fopen以模式mode打开明为path的文件,linux不区分文本模式和二进制模式。fopen返回一个文件指针,该指针可以传递给别的标准I/O函数来标识这个流。文件指针只想一个描述流的结构。在出现错误的情况下,fopen返回NULL并把errno变量设置为恰当的值。如果用fopen打开供写入数据的文件不存在
那么会以0666权限来创建该文件。

freopen打开在path中指定的文件,并把它和stream指向的文件关联起来,这个函数吧文件指针关闭后重新打开,于是文件指针指向新的文件。
典型的用途在于重定向流stdout,stdin和stderr

fdopen函数把一个文件指针和文件描述符filedes关联起来。

2 读写文件
fread和fwrite允许从文件流读出数据以及想文件流写入数据

#include<stdio.h>
size_t fread(void *ptr,size_t size,size_t nmemb,FILE*stream);
size_t fwrite(void *ptr,size_t size,size_t nmemb,FILE*stream);
指针ptr指向的缓冲区保存fread从文件读入的数据或者保存fwrite向文件写回的数据。
stream只想要出操作的数据流
size和nmemb分别控制读入或写回的一条记录的大小和记录数
size是指读写的字节数,nmemb是指读写多少个单位的size

fread返回读入的记录数
fwrite返回写回的记录数而不是字节数

3 获得文件状态
feof和ferror函数都返回流的当前状态。clearerr清除在文件上已经设置的错误位,fileno返回与给定的文件流相关联的文件描述符。
int feof(FILE *stream);
int ferror(FILE *stream);
int clearerr(FILE *stream);
int fileno(FILE *stream);

int c;
while((c=fgetc(stream))!=EOF)
{
   /*do stuff*/
}

3 输入输出调用
用于格式化输出的printf函数、用于格式化输入的scanf函数、用于字符输入和输出的例程、基于行的输入和输出调用、以及取得和设置文件指针的调用。
#include<stdio.h>
int printf(const char *fromat,.....);
int fprintf(FILE *stream,const char *format,....);
int sprintf(char *str,consta char *format,.....);
int snprintf(char *str,size_t size,const char *format,...);

#include<stdarg.h>
int vprintf(const char *fromat,va_list ap);
int vfprintf(FILE *stream,const char *format,va_list ap);
int vsprintf(char *str,consta char *format,va_list ap);
int vsnprintf(char *str,size_t size,const char *format,va_list ap);

以“s”开头的函数向一个字符串而不是一个流输出结果
以“sn”开头的函数检查传递给他们的参数长度

在<stdarg.h>中声明的宏vararg解决了传递给函数的参数个数以及类型都不确定的问题。

格式化输入:

#include<stdio.h>
int scanf(const char *fromat,.....);
int fscanf(FILE *stream,const char *format,....);
int sscanf(char *str,const  char *format,.....);

#include<stdarg.h>

int vscanf(const char *fromat,va_list ap);
int vsscanf(char *str,const char *format,va_list ap);
int vfscanf(FILE *stream,const char *format,va_list ap);

4 字符输入输出
#include<stdio.h>
int fgetc(FILE *stream);
int fetc(FILE *stream);
int getchar(void);
int ungetc(int c,FILE *stream);
int fputc(int c,FILE *stream);
int putc(int c,FILE *stream);
int putchar(int c);

getchar()和putchar()通常是由宏实现的,所以在有的地方使用它们要小心。

4 行输入输出
#include<stdio.h>
char *fgets(char *s,int size,FILE *stream);
char *gets(char *s);
int fpugs(const char *s,FILE *stream);
int puts(const char *s);

gets不能很好的处理缓冲区溢出问题,应用fgets代替,fgets保留新行的行终止符,而gets却不保留。

5 文件定位
文件定位函数设置文件内部的当前位置,他们对没有指向普通文件的流,如套接口和管道不起作用。
#include <stdio.h>
int fseek(FILE *stream,long offset,int whence);
long ftell(FILE *stream);
int fgetpos(FILE *stream,fpos_t *pos);
int fsetpos(FILE *stream,fops_t *pos);
void rewind(FILE *stream);

fseek函数把当前位置设置到offset处,参数whence可以是SEEK_SET,SEEK_CUR,SEEK_END    
ftell返回文件指针相对于文件起始位置的偏移量
rewind函数把文件指针设置为0

fgetpos fsetpos是fseek ftell的变体

6 缓冲区控制
3种主要的流缓冲机制:
无缓冲  行缓冲  块缓冲

#inlcue<stio.h>
int fflush(FILE *stream);
int setbuf(FILE *stream,char *buf);
int setbuffer(FILE *stream,char *buf,size_t size);
int setlinebuf(FILE *stream);
int setvbuf(FILE *stream,char *buf,int mode,size_t size);

fflush把缓冲区中的尚未写入设备的数据强制的写入到输出流stream上
setvbuf设置流使用的缓冲区,指向流的文件指针stream,流所用到的缓冲区buf,文件模式mode以及缓冲的大小
mode:
_IONBF用于无缓冲操作
_IOLBF用于行缓冲
_IOFBF用于完全缓冲

要改变流的缓冲模式,只需要简单地调用缓冲地址为NULL的setvbuf函数即可

7 删除和改名
remove根据提供的文件名删除文件,而函rename能改变一个文件的名字
#include<stdio.h>
int remove(const char *pathname);
int rename(const char *oldpath,const char *newpath);

8 使用临时文件
函数tmpfile和tmpnam是标准C库的组成部分
mkstemp和mktemp是unix特有的函数

#include<stdio.h>
FILE *tmpfile(void);
char *tmpnam(char *s);
tempfile打开一个临时文件,返回一个只想FILE结构的指针
tmpnam用于产生临时文件的文件名,如果字符串s不为NULL,则文件名被写入所提供的缓冲区中

#include<unistd.h>
int mkstemp(char *template);
char *mktemp(char *template);
mktemp

9 目录操作
找到当前目录
#include <unistd.h>
char *getcwd(char *buf,size_t size);
getcwd把当前工作目录的绝对路径名复制到buf中,该缓冲区有size个字节长,如果buf不够大,则getcwd会返回NULL,并且把errno设置为ERANGE。
如果buf为NULL,而size又小于0,getcwd会使用malloc动态地为buf分配足够的内存

10 改变目录
#include<unistd.h>
int chdir(const char *path);
int fchdir(int fd);
chdir 把当前目录改为path所包含的新目录

11 创建和删除目录
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
int mkdir(const char *pathname,mode_t mode);
int rmdir(const char *pathname);
mkdir尝试以mode为权限建立pathname指定的目录,这和umask修改文件的权限类似。rmdir删除pathname指定的目录

12 获得目录列表
1)使用opendir函数打开目录文件
2)使用readdir函数读出目录文件的内容,如果你已经读到了目录文件的末尾,还想再从头开始,则可以使用rewinddir函数把文件指针重定位到目录文件的起始位置。
3)使用closedir函数关闭目录文件

#include<dirent.h>
#include<sys/types.h>
DIR *opendir(const char *pathname);
struct dirent *readdir(DIR *dir);
int rewinddir(DIR *dir);
int closedir(DIR *dir);
readdir函数执行了读取目录内容的大部分工作,它返回一个只想dirent结构的指针,这个结构包含了来自dir的下一条目录内容项,以后每次调用readdir都用新数据覆盖返回的dirent结构。直到达到文件末尾或者出错时。
dirent.d_name[]返回指向文件名的指针

13 特殊的ext2文件系统属性
ext2文件系统在文件上设置多达4种特殊的属性:
固定不变的(Immutable)---EXT2_IMMUTABLE_FL
文件根本不能修改
在操作之前必须要清除Immutable位

只能添加的(Append-only)---EXT2_APPEND_FL
文件只能以添加模式写入数据,而且不能删除、改名或被链接。

不能卸出的(No-dump)---EXT2_NODUMP_FL

同步(Sync)------EXT2_SYNC_FL

要取得或设置这些属性,可以使用ioctl调用
#include<sys/ioctl.h>
int ioctl(int fd,int request,void *arg);
标志的声明位于<linux/ext2_fs.h>中,要检索文件描述符fd指定的文件属性,必须吧request设定为EXT2_IOC_GETFLAGS,如果要设置上述属性,必须吧request设定为EXT2_IOC_SETFLAGS

 posted on 2009-06-08 22:22  清水湾  阅读(443)  评论(0编辑  收藏  举报