IO、阻塞和非阻塞、目录

系统函数、系统调用

系统函数

open/close函数

函数原型

man 2 open

// open, creat - open and possibly create a file or device
// The argument flags must include one  of  the  following  access  modes:
//       O_RDONLY,  O_WRONLY,  or  O_RDWR.
// 或者  O_APPEND O_CREAT O_EXCL O_TRUNC(清空文件) 
int open(const char * pathname, int flags);
  • 头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// --> 简写为
#include <unistd.h>
  • demo
#include <stdio.h>
#include <fcntl.h>  // O_RDONLY的头文件
#include <unistd.h>


int main()
{
    int fd;
    fd = open("./dict", O_RDONLY | O_CREAT);
    // 创建文件指定权限,8进制数
    fd = open("./dict", O_RDONLY | O_CREAT, 0644);
    printf(fd);
    close(fd);
    return 0;
}

read/write函数

ssize read(int fd, void *buf, size_t count);
ssize write(int fd, const void *buf, size_t count);

read参数

  • fd:文件描述符
  • buf:存放数据的缓冲区
  • count:缓冲区的大小

read返回值:

  • success:读到的字节数
  • fail:-1,设置errno

write返回值:

  • success:写入的字节数

  • error:-1

实现cp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    char buf[1024];
    int len = 0;
    int fd1 = open(argv[1], O_RDONLY);
    if(fd1 == -1)
    {
        perror("open argv1 error");
        exit(1);  // stdlib
    }
    // 打开文件,如果没有就创建,如有就清空
    int fd2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0664);

    while((len = read(fd1, buf, 1024))!=0)
    {
        if(len < 0)
        {
            perror("read error!");
            exit(1);
        }
        write(fd2, buf, len);
    }

    close(fd1);
    close(fd2);

    return 0;
}

跟踪系统调用

$ strace ./readWrite
read(-1, 0x7ffd53164ea0, 1024)          = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615)      = -1 EFAULT (Bad address)
read(-1, 0x7ffd53164ea0, 1024)          = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615)      = -1 EFAULT (Bad address)
read(-1, 0x7ffd53164ea0, 1024)          = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615)      = -1 EFAULT (Bad address)
read(-1, 0x7ffd53164ea0, 1024)          = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615)      = -1 EFAULT (Bad address)

库函数

fopen/fclose

fgetc/fputc

FILE *fp, *fp_out;
int n;
fp = fopen("./dict.txt", "rw");
if (fp == NULL) {

    perror("fopen error");
    exit(1);
}
fp_out = fopen("dict.cp", "w");
if (fp_out == NULL) {
    perror("fopen error");
    exit(1);
}
while ((n = fgetc(fp)) != EOF) {
    fputc(n, fp_out);
}
fclose(fp);
fclose(fp_out);

文件描述符

文件描述符指向文件结构体.

PCB(进程控制块) :本质是结构体,成员是文件描述符,文件描述符:01/2/3...

一个进程快最多打开1024个文件,第一个文件是stdin, 2->stdout, 3 ->stderr

阻塞、非阻塞

阻塞:当读取设备文件、网络文件。读取常规文件不会阻塞。

设备目录:

  • /dev/tty 【终端设备】

阻塞示例:

void block() {
    char buf[10];
    // 读取是个字节
    int n = read(STDIN_FILENO, buf, 10);
    if (n < 0) {
        perror("read STDIN_FILENOO");
        exit(1);
    }
    write(STDOUT_FILENO, buf, 10);
}

当以非阻塞的方式读取文件(设备文件或者网络文件),并且文件为空时,open函数返回-1,并且将errno 设置为 EAGAIN or EWOULDBLOCK

tryagain:
n = read(fd, buf, 10);
if(n<0) 
{
    if(errno!= EAGAIN) 
    {
        perror("read /dev/tty");
        exit(1);
    } 
    else
    {
        write(STDOUT_FILENO, "try again!", strlen("try again!"));
        sleep(2);
        goto tryagain;
    }
}
原文地址:https://www.cnblogs.com/zhuxiang1633/p/12317221.html