Linux操作文件的底层系统怎么调用

发布时间:2023-03-23 17:18:41 作者:iii
来源:亿速云 阅读:271

Linux操作文件的底层系统调用

引言

在Linux操作系统中,文件操作是最基本且重要的功能之一。无论是读取文件内容、写入数据,还是创建、删除文件,这些操作都依赖于底层的系统调用。系统调用是操作系统提供给用户程序的接口,允许用户程序请求操作系统执行某些特权操作。本文将深入探讨Linux中操作文件的底层系统调用,包括文件描述符、文件打开与关闭、文件读写、文件定位、文件状态获取与设置等内容。

文件描述符

在Linux中,文件描述符(File Descriptor)是一个非负整数,用于标识一个打开的文件。每个进程都有一个文件描述符表,用于记录该进程打开的文件。文件描述符表中的每个条目都指向一个文件表项,文件表项中包含了文件的打开模式、文件偏移量等信息。

文件描述符的分配

当进程打开一个文件时,内核会为该文件分配一个文件描述符。通常情况下,文件描述符从0开始分配,依次递增。标准输入、标准输出和标准错误输出的文件描述符分别为0、1和2。

int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
    perror("open");
    exit(EXIT_FLURE);
}

在上面的代码中,open系统调用返回的文件描述符存储在fd变量中。如果open调用失败,返回-1,并设置errno以指示错误原因。

文件打开与关闭

打开文件

open系统调用用于打开一个文件,并返回一个文件描述符。open函数的原型如下:

#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int fd = open("example.txt", O_RDWR | O_CREAT, 0644);
if (fd == -1) {
    perror("open");
    exit(EXIT_FLURE);
}

在上面的代码中,open系统调用以读写模式打开example.txt文件,如果文件不存在则创建它,并设置文件权限为0644

关闭文件

close系统调用用于关闭一个文件描述符,释放相关资源。close函数的原型如下:

#include <unistd.h>

int close(int fd);
if (close(fd) == -1) {
    perror("close");
    exit(EXIT_FLURE);
}

在上面的代码中,close系统调用关闭了文件描述符fd。如果close调用失败,返回-1,并设置errno以指示错误原因。

文件读写

读取文件

read系统调用用于从文件中读取数据。read函数的原型如下:

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
char buffer[1024];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read == -1) {
    perror("read");
    exit(EXIT_FLURE);
}

在上面的代码中,read系统调用从文件描述符fd中读取最多1024字节的数据,并将其存储在buffer中。如果read调用失败,返回-1,并设置errno以指示错误原因。

写入文件

write系统调用用于向文件中写入数据。write函数的原型如下:

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);
const char *data = "Hello, World!";
ssize_t bytes_written = write(fd, data, strlen(data));
if (bytes_written == -1) {
    perror("write");
    exit(EXIT_FLURE);
}

在上面的代码中,write系统调用将字符串"Hello, World!"写入文件描述符fd。如果write调用失败,返回-1,并设置errno以指示错误原因。

文件定位

lseek系统调用用于移动文件的读写位置。lseek函数的原型如下:

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
off_t new_offset = lseek(fd, 10, SEEK_SET);
if (new_offset == -1) {
    perror("lseek");
    exit(EXIT_FLURE);
}

在上面的代码中,lseek系统调用将文件描述符fd的读写位置移动到文件开头后的第10个字节。如果lseek调用失败,返回-1,并设置errno以指示错误原因。

文件状态获取与设置

获取文件状态

fstat系统调用用于获取文件的状态信息。fstat函数的原型如下:

#include <sys/stat.h>

int fstat(int fd, struct stat *buf);
struct stat st;
if (fstat(fd, &st) == -1) {
    perror("fstat");
    exit(EXIT_FLURE);
}

在上面的代码中,fstat系统调用获取文件描述符fd的状态信息,并将其存储在st结构体中。如果fstat调用失败,返回-1,并设置errno以指示错误原因。

设置文件权限

fchmod系统调用用于设置文件的权限。fchmod函数的原型如下:

#include <sys/stat.h>

int fchmod(int fd, mode_t mode);
if (fchmod(fd, 0644) == -1) {
    perror("fchmod");
    exit(EXIT_FLURE);
}

在上面的代码中,fchmod系统调用将文件描述符fd的权限设置为0644。如果fchmod调用失败,返回-1,并设置errno以指示错误原因。

文件链接与删除

创建硬链接

link系统调用用于创建一个硬链接。link函数的原型如下:

#include <unistd.h>

int link(const char *oldpath, const char *newpath);
if (link("example.txt", "example_link.txt") == -1) {
    perror("link");
    exit(EXIT_FLURE);
}

在上面的代码中,link系统调用为example.txt文件创建了一个名为example_link.txt的硬链接。如果link调用失败,返回-1,并设置errno以指示错误原因。

删除文件

unlink系统调用用于删除一个文件。unlink函数的原型如下:

#include <unistd.h>

int unlink(const char *pathname);
if (unlink("example.txt") == -1) {
    perror("unlink");
    exit(EXIT_FLURE);
}

在上面的代码中,unlink系统调用删除了example.txt文件。如果unlink调用失败,返回-1,并设置errno以指示错误原因。

文件重命名

rename系统调用用于重命名或移动文件。rename函数的原型如下:

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);
if (rename("example.txt", "new_example.txt") == -1) {
    perror("rename");
    exit(EXIT_FLURE);
}

在上面的代码中,rename系统调用将example.txt文件重命名为new_example.txt。如果rename调用失败,返回-1,并设置errno以指示错误原因。

文件同步

fsync系统调用用于将文件数据同步到磁盘。fsync函数的原型如下:

#include <unistd.h>

int fsync(int fd);
if (fsync(fd) == -1) {
    perror("fsync");
    exit(EXIT_FLURE);
}

在上面的代码中,fsync系统调用将文件描述符fd的数据同步到磁盘。如果fsync调用失败,返回-1,并设置errno以指示错误原因。

文件锁定

fcntl系统调用用于对文件进行锁定操作。fcntl函数的原型如下:

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();

if (fcntl(fd, F_SETLK, &fl) == -1) {
    perror("fcntl");
    exit(EXIT_FLURE);
}

在上面的代码中,fcntl系统调用对文件描述符fd设置了一个写锁。如果fcntl调用失败,返回-1,并设置errno以指示错误原因。

文件映射

mmap系统调用用于将文件映射到内存中。mmap函数的原型如下:

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
void *addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FLED) {
    perror("mmap");
    exit(EXIT_FLURE);
}

在上面的代码中,mmap系统调用将文件描述符fd的前4096字节映射到内存中。如果mmap调用失败,返回MAP_FLED,并设置errno以指示错误原因。

文件截断

ftruncate系统调用用于截断文件到指定长度。ftruncate函数的原型如下:

#include <unistd.h>

int ftruncate(int fd, off_t length);
if (ftruncate(fd, 1024) == -1) {
    perror("ftruncate");
    exit(EXIT_FLURE);
}

在上面的代码中,ftruncate系统调用将文件描述符fd的文件截断为1024字节。如果ftruncate调用失败,返回-1,并设置errno以指示错误原因。

文件描述符复制

dupdup2系统调用用于复制文件描述符。dupdup2函数的原型如下:

#include <unistd.h>

int dup(int oldfd);
int dup2(int oldfd, int newfd);
int new_fd = dup(fd);
if (new_fd == -1) {
    perror("dup");
    exit(EXIT_FLURE);
}

在上面的代码中,dup系统调用复制了文件描述符fd,并返回一个新的文件描述符new_fd。如果dup调用失败,返回-1,并设置errno以指示错误原因。

if (dup2(fd, new_fd) == -1) {
    perror("dup2");
    exit(EXIT_FLURE);
}

在上面的代码中,dup2系统调用将文件描述符fd复制到new_fd。如果dup2调用失败,返回-1,并设置errno以指示错误原因。

文件描述符控制

fcntl系统调用还可以用于控制文件描述符的属性。fcntl函数的原型如下:

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );
int flags = fcntl(fd, F_GETFD);
if (flags == -1) {
    perror("fcntl");
    exit(EXIT_FLURE);
}

flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1) {
    perror("fcntl");
    exit(EXIT_FLURE);
}

在上面的代码中,fcntl系统调用获取文件描述符fd的标志,并设置FD_CLOEXEC标志。如果fcntl调用失败,返回-1,并设置errno以指示错误原因。

文件描述符的异步I/O

aio_readaio_write系统调用用于进行异步I/O操作。aio_readaio_write函数的原型如下:

#include <aio.h>

int aio_read(struct aiocb *aiocbp);
int aio_write(struct aiocb *aiocbp);
struct aiocb aio;
aio.aio_fildes = fd;
aio.aio_buf = buffer;
aio.aio_nbytes = sizeof(buffer);
aio.aio_offset = 0;

if (aio_read(&aio) == -1) {
    perror("aio_read");
    exit(EXIT_FLURE);
}

在上面的代码中,aio_read系统调用从文件描述符fd中异步读取数据到buffer中。如果aio_read调用失败,返回-1,并设置errno以指示错误原因。

if (aio_write(&aio) == -1) {
    perror("aio_write");
    exit(EXIT_FLURE);
}

在上面的代码中,aio_write系统调用将buffer中的数据异步写入文件描述符fd。如果aio_write调用失败,返回-1,并设置errno以指示错误原因。

文件描述符的轮询

poll系统调用用于轮询多个文件描述符的状态。poll函数的原型如下:

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;

int ret = poll(fds, 1, 1000);
if (ret == -1) {
    perror("poll");
    exit(EXIT_FLURE);
}

在上面的代码中,poll系统调用轮询文件描述符fd的状态,等待1秒钟。如果poll调用失败,返回-1,并设置errno以指示错误原因。

文件描述符的选择

select系统调用用于监视多个文件描述符的状态。select函数的原型如下:

#include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

”`c fd_set read_fds; FD_ZERO(&read_fds); FD_SET(fd, &read_fds

推荐阅读:
  1. Linux中如何运行Android应用
  2. 进程间通信的Linux小程序问题怎么解决

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

linux

上一篇:如何修改配置文件php.ini

下一篇:怎么用Python写一个京东自动下单抢购脚本

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》