c程序设计语言 by K&R(五)UNIX系统接口

一、文件描述符

  1. 在unix操作系统中,所有的外围设备(包括键盘和显示器)都被看作是文件系统的文件,因此,所有的输入、输出都要通过读/写文件来完成。也就是说,通过一个单一的接口就可以处理外围设备和程序之间的所有通信。

  2. 读写文件前,需要打开文件。若系统检查文件存在,有访问权限,OS将向程序返回一个非负整数——文件描述符。系统负责维护已打开文件的所有信息,用户程序只能通过文件描述符引用文件。

  3. 命令解释程序(shell)运行程序时,将打开三个文件,对应文件描述符0、1、2, 依次表示stdin,stdout,stderr。

  4. 程序使用者可通过<>重定向程序的I/O。
    prog < 输入文件名
    prog > 输出文件名

  5. 文件指针和文件描述符的区别

C语言中使用文件指针做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括缓冲区和文件描述符。而文件描述符是文件描述符表的一个索引,也就是说c语言的文件指针是Linux系统中对文件描述符的一种封装。

二、低级I/O —— read和write

  1. 输入和输出时通过read和write系统调用实现的。

int n_read = read(int fd, char* buf, int n);
int n_written = write(int fd, char* buf, int n);

第一个参数是文件描述符,第二个参数是存放或读写的数据字符数组,第三个参数是要传输的字节数。

  1. 系统调用的函数原型都放在 syscalls.h 中。

三、open、creat、close和unlink

除了默认的stdin、 stdout、 stderr,其它文件都必须在读或写之前显式地打开。系统调用open、creat用于实现该功能。

  1. open 用于返回一个文件描述符。

  2. creat 用于创建一个文件,创建成功将返回一个文件描述符。

  3. unlink将文件从文件系统中删除,对应于标准库函数remove。

  4. 实现cp程序

#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include "syscall.h"
#include <unistd.h>
#define PERMS 0666
void error(char*, ...);

int main(int argc, char* argv[]) {
    int f1, f2, n;
    char buf[BUFSIZ];
    if(argc != 3){
        error("Usage: cp from to");
    }
    if((f1 = open(argv[1], O_RDONLY, 0)) == -1){
        error("%s: can't open %s", argv[0],argv[1]);
    }
    if((f2 = creat(argv[2], PERMS)) == -1){
        error("%s: can't create %s, mode %03o", argv[0], argv[2], PERMS);
    }
    while((n = read(f1, buf, BUFSIZ)) > 0){
        if(write(f2, buf, n) != n){
            error("%s: write error on file %s", argv[0], argv[2]);
        }
    }
    return 0;
}

void error(char* fmt, ...){
    va_list args;
    va_start(args, fmt);
    fprintf(stderr, "error:");
    vprintf((const char *) stderr, args);
    fprintf(stderr, "\n");
    va_end(args);
    exit(1);
}

四、随机访问——lseek

  1. long lseek(int fd, long offset, int origin)

offset是相当于origin指定位置的偏移。
origin为0、1、2用于指定offset从文件开始、从当前位置或从文件结束处开始算起。

  1. 写操作找到文件的末尾

lseek(fd, 0L, 2);

  1. 文件的开始处

lseek(fd, 0L, 0);

posted on 2022-01-18 00:07  七昂的技术之旅  阅读(228)  评论(0)    收藏  举报

导航