文章目录
- 前言
- 一、基础命令简单讲解
- 二、文件描述符
- 三、open、read、write函数讲解
- 1.open函数
- 2.read函数
- 3.write函数
- 四、使用open、read、write操作标准输入输出
- 总结
前言
Linux是一个基于文件系统的操作系统,文件操作是其中一项最基本的任务之一。通过文件操作,用户可以创建、移动、复制、读取和修改文件及目录等。
一、基础命令简单讲解
1.ls:列出目录中的文件和子目录。
ls -a:显示所有包括隐藏文件。
ls -l:使用长格式输出文件详细信息。
ls -h:显示文件大小时使用易读的格式。
cd:切换当前目录。
2.cd /:切换到根目录。
cd ~:切换到当前用户的主目录。
cd …:切换到上级目录。
mkdir:创建目录。
3.mkdir dir1:创建一个名为“dir1”的目录。
mkdir -p dir1/dir2:创建多层目录。
rm:删除文件或目录。
4.rm file1:删除一个名为“file1”的文件。
rm -r dir1:删除整个名为“dir1”的目录。
cp:复制文件或目录。
5.cp file1 file2:将“file1”复制到“file2”。
cp -r dir1 dir2:将“dir1”及其内容复制到“dir2”。
mv:移动文件或目录。
6.mv file1 dir1:将“file1”移动到“dir1”中。
mv dir1 new_dir:将“dir1”重命名为“new_dir”。
touch:创建空文件或者修改文件访问时间和修改时间。
7.touch file1:创建一个名为“file1”的空文件。
touch -a file1:修改“file1”的访问时间。
touch -m file1:修改“file1”的修改时间。
cat:显示文件内容。
8.cat file1:显示“file1”的内容。
cat file1 file2:顺序显示“file1”和“file2”的内容。
grep:在文件中搜索特定的字符串。
grep “my text” file1:搜索“file1”中包含“my text”的行。
具体的命令讲解可以看我之前写的文章这里就不做过多讲解。本篇文章主要来学习基本I/O函数的使用。
二、文件描述符
在 Linux 系统中,每一个打开的文件或者流都会分配一个唯一的整数标识符,称为文件描述符。文件描述符是操作系统用来标识一个进程所持有的文件或者数据流的方式。
文件描述符是一个非负整数值,通常是一个小于或等于进程打开文件限制的值。标准输入(stdin)、标准输出(stdout)和标准错误(stderr)的文件描述符分别为0,1和2。
文件描述符在打开文件和数据流时由操作系统赋予。当操作系统打开文件或数据流时,会分配一个文件描述符并返回给调用进程。进程可以使用此文件描述符进行读写操作。
三、open、read、write函数讲解
1.open函数
man手册查看用法:
在man手册中可以查看到所需要的头文件和函数原型。
函数原型:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
下面是open()函数的参数详解:
pathname:文件路径名字符串,为要打开的文件的绝对或相对路径名。
flags:打开标志位参数,可通过将不同的标志位进行按位或运算来组合使用,其值为以下标志位的按位或:
O_RDONLY:以只读方式打开文件。
O_WRONLY:以只写方式打开文件。
O_RDWR:以读写方式打开文件。
O_CREAT:如果文件不存在,则创建文件。必须与mode_t位运算标志位O_WRONLY、O_RDWR组合使用。
O_EXCL:如果同时设置了O_CREAT标志,而文件已经存在,则返回错误。
O_TRUNC:如果文件存在并且以写方式打开,则清空文件所有数据。
O_APPEND:以追加方式打开文件。在写入时,总是从文件末尾开始添加数据。
O_NONBLOCK:以非阻塞方式打开文件。如果文件没有准备好,那么读取操作和写入操作将直接返回错误而不是等待。
O_SYNC:由于写入将是同步的,因此所有上层缓存都将被刷新。这通常会降低文件I/O的性能。
O_DIRECTORY:要求pathname必须是一个目录。
mode:默认权限,指定了文件创建时的访问权限。它是一个八进制数,由三个低权限位(对应文件所有者、组和其它人)以及三个特殊位(SGID、SUID和sticky位)构成。特殊位通常默认设置为0。
在调用open()之后,如果文件打开成功,它将返回一个文件描述符(file descriptor)。返回的文件描述符就是要操作的文件句柄,我们可以使用它进行读、写等各种操作,如果返回-1则表示打开文件失败,此时可以使用errno来获取失败原因。
2.read函数
man手册查看用法:
函数原型:
read函数是Linux系统提供的输入函数之一,通常用于从文件或套接字中读取数据
ssize_t read(int fd, void *buf, size_t count);
参数解析:
fd:要读取数据的文件描述符,通常是打开文件时返回的文件描述符,也可以是套接字描述符等。
buf:读取数据后存储的位置,一般为一块已分配的内存地址。
count:要读取的字节数。
return值解释如下:
成功时,返回实际读取的字节数(可能小于count);
如果已经到达文件末尾,则返回0;
如果发生错误,则返回-1,并设置全局变量errno来指示发生的错误类型。
read函数在执行时有以下三种基本情况:
当count大于零时,read函数一直等待直到读取指定数量的字节,或者读取到文件末尾。
当count等于零时,read函数不会读取数据,而只是返回0。
当count小于零时,read函数将返回EINVAL错误。
需要注意的是,read函数是一个阻塞函数,如果在读取数据时没有足够的数据可用,它将一直等待直到读取指定数量的字节或者遇到错误。为了避免read函数一直等待的问题,可以使用非阻塞的I/O或者使用select等函数来监视可读取的数据。
3.write函数
man手册查看用法:
函数原型:
在Linux系统中,write()函数是一个用于向文件描述符(file descriptor)写入数据的系统调用函数。
ssize_t write(int fd, const void *buf, size_t count);
参数解析:
fd:可通过open()函数或socket()函数创建。在Linux中,文件和设备都是通过文件描述符来访问的。例如,标准输入(standard input)的文件描述符是0,标准输出(standard output)的文件描述符是1,标准错误(standard error)的文件描述符是2。
buffer:指向要写入数据的缓冲区指针。注意,这里的缓冲区是指一个内存块,可以是栈上的数组变量、堆上动态分配的空间或静态分配的内存等。缓冲区最大长度为SSIZE_MAX,一般情况下为32767字节。
count:指定要写入的数据字节数。如果count为0,则write()函数不进行任何操作并返回0。如果count超过了缓冲区的长度,则只有缓冲区的长度部分的数据会被写入。
四、使用open、read、write操作标准输入输出
标准输入的文件路径是"/dev/stdin",标准输出的文件路径是"/dev/stdout"。使用open函数打开后会得到对应的文件标识符,得到文件描述符后就可以进行相应的读写操作了。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char buffer[100];
ssize_t nread;
// 打开标准输入文件描述符
int fd = open("/dev/stdin", O_RDONLY);
// 从标准输入读取数据
nread = read(fd, buffer, sizeof(buffer) - 1);
if (nread == -1) {
printf("read err\n");
}
buffer[nread] = '\0';
printf("Read %zd bytes from standard input: %s", nread, buffer);
// 关闭标准输入文件描述符
close(fd);
// 打开标准输出文件描述符
fd = open("/dev/stdout", O_WRONLY);
// 向标准输出写入数据
char msg[] = "Hello, World!\n";
ssize_t nwritten = write(fd, msg, sizeof(msg));
if (nwritten == -1) {
printf("write err");
}
printf("Write %zd bytes to standard output: %s", nwritten, msg);
// 关闭标准输出文件描述符
close(fd);
return 0;
}
执行效果:
总结
本篇文章先介绍了一下文件在Linux中的重要性,然后介绍了几个常用于文件操作的函数,并且使用这几个函数直接操作了标准输入和输出。