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.
/**
* @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:
dup
Funció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.
dup2
Función: Puede especificar el nuevo descriptor de archivo para que apunte al archivo al que apunta el archivo original descriptor.