• 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);

  • 相关阅读:
    安装IDM扩展
    Go_数组&切片
    Mycat概念&安装
    IDEA自定义主题
    完全卸载Oracle11g
    创建型模式——单例模式(Singleton)
    设计模式统计
    PHP解压带密码的zip文件
    Win推荐软件
    如何设置线程池的线程数?
  • 原文地址:https://www.cnblogs.com/qiangz/p/15816038.html
Copyright © 2020-2023  润新知