版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guanchunsheng/article/details/76933626
系统接口和标准的C库,是不同的两个范畴。
标准C库,各个平台的C编译器都应该支持,具有跨平台的性质。
系统接口则是系统相关的,UNIX的系统接口,在Win上就肯定不能用。
那么两者是不是还有联系呢,其实是的。标准C库,跟系统相关的部分,不也是通过系统调用/系统接口实现的么。所以系统接口可以实现一部分的标准C库,系统接口为特定系统的程序开发提供了服务,这部分服务一般是不能跨平台的。
这是我对这个主题的理解。
文件描述符
- UNIX系统,或者linux这种UNIX like系统,所有的外围设备,都看做是文件系统的文件
- 所有的 输入/输出 都要通过读文件和写文件完成
- 正常打开文件后,操作系统会向程序返回一个小的非负整数,称为文件描述符 file descriptor
- 之后的文件访问,都通过文件描述符完成,而不是文件名
- stdin, stdout, stderr的文件描述符分别是0, 1, 2
- 下文的文件描述符简写为 fd 吧
- shell 会对不同的文件赋予 fd 0和1,以便完成重定向和管道
- 程序本身并不需要关心 fd 0, 1现在被赋予了谁
- fd 2一般还是保留到显示器上
低级I/O read 和 write
- read 和 write 是系统调用
- 所谓系统调用是UNIX提供给用户程序来调用的函数,以此提供操作系统的服务
- C语言程序通过read和write函数,使用I/O的系统调用
- 3个参数
- fd
- 字符数组
- 长度
- 返回值
- 实际传输的字符数
- read 返回0 表示达到文件结尾,返回-1表示出现错误
- write 返回与期望不相等,说明发生了错误
- 3个参数
int n_read = read(int fd, char *buf, int n);
int n_written = write(int fd, char *buf, int n);
- 一个带有缓冲区的getchar实现示例(我觉得getc也差不多,加个fd的事)
/* getchar函数:简单的带缓冲区的版本 */
int getchar(void)
{
static char buf[BUFSIZE];
static char *bufp = buf;
static int n = 0;
if (n == 0)
{
n = read(0, buf, sizeof buf);
bufp = buf;
}
return (--n >= 0)? (unsidned char) *bufp++ : EOF;
}
这里利用静态局部变量保存缓冲区数组,缓冲区指针,缓冲区有效长度。每读一次缓冲区,可以支持getchar 读n次单个字符。
open/create/close/unlink
open
- open 跟fopen 类似,但是open返回的是一个fd
- name 跟fopen一样,是文件名字符串
- flags是一个int类型的值,说明打开文件的方式
- O_RDONLY
- O_WRONLY
- O_RDWR
#include <fcntl.h>
int fd;
int open(char *name, int flags, int perms);
fd = open(name, flags, perms);
creat
- 创建新的文件,还可以覆盖旧文件
- 成功创建,返回fd
- 失败返回-1
- 覆盖文件的话,是把文件长度变为0,丢弃原来的内容
- perms用于指定文件权限
- 比如3组都是读写权限 0666
int creat(char *name, int perms);
fd = creat(name, perms);
close
- 一个程序同时打开的文件数是有限制的(通常是20)
- 处理多个文件,必须重用fd
- close (int fd) 用来断开fd和已经打开的文件的连接,释放fd给其他文件使用
unlink
- 将文件从文件系统中删除,对应于标准库函数remove
- unlink(char *name)
lseek
- long lseek(int fd, long offset, int origin)
- 将fd描述符对应的文件的当前位置设置到offset,根据origin
- 返回long类型,表示文件的新位置,错误返回-1
- origin的含义
- 0 从文件开始
- 1 从当前位置开始
- 2 从文件结束处开始
/* 为了向一个文件末尾添加内容,先找到文件末尾 */
lseek(fd, 0L, 2);
/* 反绕,回到文件开始处 */
lseek(fd, 0L, 0);
- 标准库函数有一个类似的fseek, 参数是FILE *,不是 fd, 出错返回非0