文件操作相关的系统调用,都在在内核源码的fs目录下的.c文件中。可以搜索一下
$ grep -nr SYSCALL_DEFINE fs/*.c
整理如下:
fs/aio.c | io_setup() io_destroy() io_submit() io_cancel() io_getevents() io_pgetevents() io_pgetevents_time32() io_getevents_time32() |
fs/d_path.c | getcwd() |
fs/eventfd.c | eventfd2() eventfd() |
fs/eventpoll.c | epoll_create1() epoll_create() epoll_ctl() epoll_wait() epoll_pwait() epoll_pwait2() |
fs/exec.c | uselib() execve() execveat() |
fs/fcntl.c | fcntl() fcntl64() |
fhandle | name_to_handle_at() open_by_handle_at() |
fs/file.c | dup3() dup2() dup() |
fs/filesystem.c | sysfs() |
fs/fsopen.c | fsopen() fspick() fsconfig() |
fs/ioctl.c | ioctl() |
fs/locks.c | flock() |
fs/namei.c | mknodat()/mknod() mkdirat()/mkdir() rmdir() unlinkat()/unlink() symlinkat()/symlink() linkat()/link() renameat2()/renameat()/rename() |
fs/namespace.c | umount() oldumount() open_tree() mount() fsmount() move_mount() pivot_root() mount_setattr() statmount() listmount() |
fs/open.c | truncate()/truncate64() ftruncate()/ftruncate64() fallocate() faccessat()/faccessat2() access() chdir() fchdir() chroot() fchmod()/fchmodat2()/fchmodat() chmod fchownat() chown()/lchown/fchown open()/openat()/openat2() creat() close() close_range() vhangup() |
fs/pipe.c | pipe2() pipe() |
fs/readdir.c | old_readdir() getdents() getdents64() |
fs/read_write.c | lseek() llseek() read() write() pread64() pwrite64() readv/writev preadv/preadv2 pwritev/pwritev2 sendfile/sendfile64 copy_file_rnage |
fs/select.c | select pselect6/pselect6_time32 poll/ppoll ppoll_time32 |
fs/signalfd.c | signalfd4() signalfd() |
fs/splice.c | vmsplice() splice() tee() |
fs/stat.c | stat()/lstat()/fstat() newstat/newlstat/newfstat netfstatat readlink/readlinkat stat64/lstat64/fstat64 fstatat64 statx |
fs/statfs.c | statfs/statfs64 fstatfs/fstatfs64 ustat |
fs/sync.c | sync() syncfs() fsync() fdatasync() sync_file_range() sync_file_range2() |
fs/timerfd.c | timerfd_create() timerfd_settime() timerfd_gettime() timerfd_settime32() timerfd_gettime32() |
fs/userfaultfd.c | userfaultfd() |
fs/utimes.c | utimensat futimesat utimes utime32 utimensat_time32 futimesat_time32 utimes_tim32 |
fs/xattr.c | setxattr/lsetxattr/fsetxattr lgetxattr/getxattr/fgetxattr listxattr/llistxattr/flistxattr removexattr lremovexattr fremovexattr |
新学习到的几个系统调用:
int name_to_handle_at(int dirfd, const char *pathname,
struct file_handle *handle,
int *mount_id, int flags);
int open_by_handle_at(int mount_fd, struct file_handle *handle,
int flags);
name_to_handle_at(),返回特定文件的透明的file handle
struct file_handle {
unsigned int handle_bytes; /* Size of f_handle [in, out] */
int handle_type; /* Handle type [out] */
unsigned char f_handle[0]; /* File identifier (sized by
caller) [out] */
};
这个handle唯一标识了这个文件。然后可以用这个handle,去执行open动作。这样就免去了用路径去标识。在NFS系统中很有用。
一个例子,打印文件的file handle内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #define _GNU_SOURCE #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> int main( int argc, char **argv) { char *path = argv[1]; struct file_handle handle = { .handle_bytes = 0, }; int ret; int mount_id = 0; struct file_handle *phandle; ret = name_to_handle_at(AT_FDCWD, path, &handle, &mount_id, 0); if (ret < 0) { if ( errno != EOVERFLOW) { fprintf (stderr, "name_to_handle_at() get handle bytes failed: %m\n" ); return 1; } } phandle = calloc (1, sizeof ( struct file_handle) + handle.handle_bytes); if (!phandle) { fprintf (stderr, "malloc() failed: %m\n" ); return 1; } phandle->handle_bytes = handle.handle_bytes; ret = name_to_handle_at(AT_FDCWD, path, phandle, &mount_id, 0); if (ret < 0) { fprintf (stderr, "name_to_handle_at() failed: %m\n" ); return 1; } printf ( "path %s\n" , path); printf ( "mount_id: %d\n" , mount_id); printf ( "handle bytes: %d\n" , phandle->handle_bytes); printf ( "handle type: %d\n" , phandle->handle_type); printf ( "handle:" ); for (ret = 0; ret < phandle->handle_bytes; ret++) printf ( " %02x" , phandle->f_handle[ret]); printf ( "\n" ); return 0; } |
$ ./a.out file_handle.c
path file_handle.c
mount_id: 50
handle bytes: 20
handle type: 77
handle: 7f 78 e8 00 00 00 00 00 01 01 00 00 00 00 00 00 3b 01 01 00
$ stat file_handle.c
File: file_handle.c
Size: 1136 Blocks: 8 IO Block: 4096 regular file
Device: 0,50 Inode: 15235199 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ yuanjp) Gid: ( 1000/ yuanjp)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2025-02-16 11:05:43.151116796 +0800
Modify: 2025-02-16 11:05:41.245140071 +0800
Change: 2025-02-16 11:05:41.255139948 +0800
Birth: 2025-02-16 11:05:41.245140071 +0800
$ printf "%x\n" 15235199
e8787f
在这个btrfs里面。可以看到handle bytes是20个字节。前8个字节是inode id。后面0101是257是subvolume id。
这个接口创建一个处理page faults的文件描述符。通常用来先user space paging。
当一个线程发生page faults时,可以在另外一个线程接收相关消息,然后分配内存。