1 archivo de Linux de lectura y escritura


Prefacio (incluido el índice)


El número de descriptor de archivo predeterminado de Linux es 1024,
vista de comandos disponible

ulimit -n

Los tres primeros están ocupados por defecto

// stdin
#define STDIN_FILENO	0;
// stdout
#define STDOUT_FILENO	1;
// stderr
#define STDERR_FILENO	2;
/**
 * @author IYATT-yx
 * @brief 读取一个文件,并写入另外一个文件(不存在则创建)
 */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    
    
    if (argc != 3)
    {
    
    
        printf("请指定两个参数,分别为 [源文件] [目标文件]\n");
        return -1;
    }
    
    // 打开源文件,若执行失败,open内部会设置 errno 值,并返回 -1
    // perrno根据 errno 的值,输出对应错误信息
    int fdRead = open(argv[1], O_RDONLY);
    if (fdRead == -1)
    {
    
    
        perror("read file");
        return -1;
    }

    // 打开或不存在就创建将要写入的目标文件
    // 指定生成的文件权限为 0664 ,实际文件的权限为 0664 & ~umask
    int fdWrite = open(argv[2], O_WRONLY | O_CREAT, 0664);
    if (fdWrite == -1)
    {
    
    
        perror("write file");
        return -1;
    }

    char buf[4096];
    ssize_t len;

    // 从文件描述符 fdRead 读取 buf 容量大小的数据到 buf 中, 返回值为实际读取的数据长度, 返回 0 读完,返回 -1 失败
    while ((len = read(fdRead, buf, sizeof(buf))) > 0)
    {
    
    
        // 将 buf 中 len 长度的数据写入 fdWrite 文件描述符对应打开的文件, 返回 -1 代表失败!
        ssize_t ret = write(fdWrite, buf, (size_t)len);
        if (ret == -1)
        {
    
    
            perror("write");
            return -1;
        }
    }

    // 关闭文件描述符
    close(fdRead);
    close(fdWrite);
}

Mueva el puntero del archivo a la cabeza

lseek(fd, 0, SEEK_SET);

Obtener la posición actual del puntero del archivo

off_t idx = lseek(fd, 0, SEEK_CUR);

Obtener la longitud del archivo

off_t len = lseek(fd, 0. SEEK_END);

Expansión de archivos (por ejemplo, puede crear un archivo en blanco cuando comienza a descargar y expandir el archivo de descarga local al mismo tamaño de acuerdo con el tamaño del archivo que se descargará para ocupar el espacio, y luego reemplazar los datos expandidos y llenos desde el principio al descargar)

// 拓展 1KB 大小
off_t size = 1024;
lseek(fd, size, SEEK_END);
// 拓展后进行write才有效,写入内容任意,比如这里以空格结尾
const char *str = " ";
write(fd, str, 1);



/**
 * @author IYATT-yx
 * @brief 阻塞读终端
 */
#include <stdio.h>
#include <unistd.h>

int main(void)
{
    
    
    char buf[5];
    ssize_t len = read(STDIN_FILENO, buf, 5);
    if (len == -1)
    {
    
    
        perror("open STDIN_FILENO");
        return -1;
    }
    write(STDOUT_FILENO, buf, (size_t)len);
}

Después de compilar y ejecutar este programa, el terminal esperará la entrada del usuario y se detendrá en la función de lectura hasta que se presione la entrada e ingrese, y los primeros cinco de la entrada (menos de 5 caracteres son el número de entrada real) se leen en buf , El siguiente paso es ejecutar escribir para imprimir el contenido de buf en la terminal.Cuando
los caracteres de entrada están dentro de 5 establecidos por lectura, puede que no haya diferencia, pero si los datos de entrada exceden de 5, es posible que vea otro fenómeno. Los primeros 5 caracteres se mostrarán normalmente, y los siguientes caracteres se mostrarán después del símbolo del sistema y se ejecutarán como un comando. La razón de este fenómeno: cuando el programa aquí se ejecuta, el programa actúa como primer plano y el terminal cambia Este programa solo obtiene los primeros 5 caracteres y emite los caracteres obtenidos. Una vez finalizado, el programa finaliza, el terminal se cambia al primer plano y los caracteres que se exceden cuando se ejecuta el programa se aceptan y ejecutan en el Mismo tiempo.
Inserte la descripción de la imagen aquí

/**
 * @author IYATT-yx
 * @brief 非阻塞读终端
 */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <errno.h>

int main(void)
{
    
    
    int fdRead = open("/dev/tty", O_RDONLY | O_NONBLOCK);
    if (fdRead == -1)
    {
    
    
        perror("open /dev/tty");
        return -1;
    }
    char buf[4];
    ssize_t len;
    while (true)
    {
    
    
        len = read(fdRead, buf, sizeof(buf));
        if (len == -1)
        {
    
    
            if (errno == EAGAIN)
            {
    
    
                printf("请重试!\n");
                sleep(3);
                continue;
            }
            perror("read /dev/tty");
            return -1;
        }
        write(STDOUT_FILENO, buf, (size_t)len);
        close(fdRead);
        return 0;
    }
}

En el terminal de lectura sin bloqueo, cuando no hay entrada, no se detendrá en la posición de lectura y esperará la entrada, sino que continuará ejecutándose.

ps:
los atributos de los archivos ordinarios no están bloqueados de forma predeterminada.
Los dispositivos terminales, las tuberías y los archivos de socket están bloqueados de forma predeterminada


Copiar descriptor de archivo:
dupFunción: Devuelve el nuevo descriptor de archivo (el más pequeño desocupado) que también apunta al archivo al que apunta el descriptor de archivo original.
dup2Función: Puede especificar el nuevo descriptor de archivo para que apunte al archivo al que apunta el archivo original descriptor.

Supongo que te gusta

Origin blog.csdn.net/weixin_45579994/article/details/112690496
Recomendado
Clasificación