• Unix系统编程(一)


    主要内容:文件输入/输出的系统调用。

    在Linux中,万事万物皆文件。

    文件描述符的概念

    通用I/O模型的系统调用:

    打开文件 open

    关闭文件 close

    向文件写数据 write

    从文件读数据 read

    这些系统调用不仅可以对普通的文件类型进行操作,也可以对管道、终端等所有类型的文件施以输入/输入操作。

    所有执行I/O操作的系统调用都以文件描述符,一个非负整数(通常是小整数),来指代打开的文件。

    用文件描述符表示所有类型的已打开文件,包括管道(pipe)、FIFO、socket、终端、设备和普通文件。(至今只操作过普通文件,其他几个类型还没接触过)

    针对每个进程,文件描述符都自成一套。(没看懂)

    3个标准的文件描述符

    当在shell中操作的时候,有3个文件描述符始终是打开的。

    在交互式的shell中,这个3个文件描述符通常指向shell运行所在的终端。(就是我们远程连接时候的屏幕?)

    如果命令行制定对输入/输出进行重定向操作,那么shell会对文件描述符做适当修改,然后再启动程序。

    文件描述符             用途               POSIX名称                     stdio流

    0                        标准描述符         STDIN_FILENO              stdin

    1                         标准输出            STDOUT_FILENO          stdout

    2                         标准错误            STDERR_FILENO           stderr

    这里的意思是虽然shell开始会用0,1,2来这三个文件描述符代替标准输入,标准输入和标准错误,但是这种操作就像是给变量赋初始值一样。这些文件描述符并没有绑死,而是可以用freopen系统调用指向其他的任何文件对象。

    fd = open(pathname, flags, mode)

    打开pathname所标识的文件,并返回文件描述符,这个文件描述符就代表了打开的文件,并且在函数调用中用这个描述符就好了。

    如果要打开的文件不存在,open()函数可以创建它,但是这取决于flags中的选项。

    flags还指定了文件的打开方式:只读、只写或者是读写方式。

    mode指定了由open()调用创建文件的访问权限(u,o,g,w, x,r),如果open()函数并没有创建文件,那么可以忽略或省略mode参数。

    马丹,这块不熟,一个系统调用涉及到的东西这么多。

    numread = read(fd, buffer, count)

    从fd所指代的文件读取至多count字节的数据,并存储到buffer中。read()调用的返回值为实际读取到的字节数。如果再无字节可读(例如:读到文件结尾符EOF时),则返回0。

    numwrite = write(fd, buffer, count)

    从buffer中读取多达count字节的数据写入由fd指代的已打开文件中,write()调用的返回值为实际写入文件中的字节数,且有可能小于count。

    status = close(fd)

    在所有的输入/输出操作完成以后,调用close(),释放文件描述符fd以及与之相关的内核资源。

    例子:用通用I/O系统调用实现一个简版的cp命令

     1 #include <unistd.h>
     2 #include <stdio.h>
     3 #include <sys/stat.h>
     4 #include <sys/types.h>
     5 #include <fcntl.h>
     6 
     7 int main(int argc, char **argv) {
     8   int fd1, fd2, count=0;
     9   char bufs[512];
    10 
    11   if(argc < 2) {
    12     printf("Usage is error: ./mycp argv1 argv2.
    ");
    13     return -1;
    14   }
    15 
    16   fd1 = open(argv[1], O_RDONLY, 0755);
    17   if(fd1 < 0) {
    18     printf("open %s error
    ", argv[1]);
    19     return -1;
    20   }
    21 
    22   fd2 = open(argv[2], O_RDWR|O_CREAT, 0755);
    23   if(fd2 < 0) {
    24     printf("open %s error
    ", argv[2]);
    25     return -1;
    26   }
    27 
    28   while( (count = read(fd1, bufs, 100)) > 0) {
    29     write(fd2, bufs, count);
    30   }
    31   close(fd1);
    32   close(fd2);
    33 }

    然后,顺手写了一个简单的Makefile,因为这几天在看make。

    # this is my Makefile for mycp
    mycp: mycp.o
            cc -o mycp mycp.o
    mycp.o: cp.c
            cc -c cp.c -o mycp.o
    
    .PHONY: clean
    clean:
            -rm mycp mycp.o

    好像代码插件没有Makefile,那就先用bash的风格吧

  • 相关阅读:
    测试产品
    三年回顾
    测试服务输出业务价值
    慎用重载_2
    慎用重载_1
    ByteBuffer和String的互相转换
    线程较为深的度剖析1
    线程同步的故事描述
    Java线程同步
    TCP关闭过程
  • 原文地址:https://www.cnblogs.com/tuhooo/p/8628272.html
Copyright © 2020-2023  润新知