C程序设计语言(六)UNIX系统接口

版权声明:本文为博主原创文章,未经博主允许不得转载。 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 返回与期望不相等,说明发生了错误
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给其他文件使用
  • 将文件从文件系统中删除,对应于标准库函数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

待续, ls和Malloc的实现

猜你喜欢

转载自blog.csdn.net/guanchunsheng/article/details/76933626