什么会导致 "regular" 类型的文件在 Linux 中不可读以及如何识别它
What can cause a "regular" type file not to be readable in Linux and how to identify this
我正在遍历我的整个文件系统,使用诸如幻数之类的标识符来寻找某些类型的文件。
我偶然发现了一些应该是 "regular" (DT_REG) 类型的文件,但是文件无法读取(read
系统调用returns 错误 38 - 系统调用未实现)。这些文件名为 "alloc_calls",位于“/sys/kernel/slab/:d-xxxxxxx/”(其中 xxxxxxx 是一个类似于 0001024 的数字)。
这是其中一个文件的 ls -l
、file
和 cat
的输出:
root@VMint:/# ls -l /sys/kernel/slab/:d-0001024/alloc_calls
-r-------- 1 root root 4096 Aug 8 18:55 /sys/kernel/slab/:d-0001024/alloc_calls
root@VMint:/# file /sys/kernel/slab/:d-0001024/alloc_calls
/sys/kernel/slab/:d-0001024/alloc_calls: ERROR: cannot read /sys/kernel/slab/:d-0001024/alloc_calls' (Function not implemented)
root@VMint:/# cat /sys/kernel/slab/:d-0001024/alloc_calls
cat: '/sys/kernel/slab/:d-0001024/alloc_calls': Function not implemented
我写了一些 C 代码来证明这一点:
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
void main()
{
char buf;
int fd = open("/sys/kernel/slab/:d-0001024/alloc_calls", 0);
perror("open");
read(fd, &buf, 1);
perror("read");
printf("fd: %d, errno: %d\n",fd, errno);
}
执行这段代码得到:
# gcc ./enosys.c -o enosys
# c_test sudo ./enosys
open: Success
read: Function not implemented
fd: 3, errno: 38
普通文件怎么会是root无法读取的呢?另外,如何识别此类文件?
/proc
和 /sys
中的文件很神奇。它们不是真正的文件——当您读写它们时,您实际上是在读写各种内核数据结构。 (mount
命令将显示它们都是挂载的文件系统,类型分别为 proc
和 sysfs
。)
对于任何存在于这些目录中的任何 "file",这意味着存在一个内核数据结构,有人认为以这种方式公开它可能有用。为了进行公开,必须设置不同的代码来实现 read()
从数据结构中获取,而 write()
存储到它。
因此,对于以这种方式公开的给定内核数据结构,如果某人实际所做的是在特定数据结构上实现(比如说)写而不是读,您会看到这样的结果。
当您调用 read()
时实际发生的是内核查找文件系统,也许还有您正在读取的单个文件,应该使用 read
的哪个设备相关实现对于那个文件。如果没有,则错误是(很自然地)ENOSYS "syscall not implemented".
Also, how can I identify such files?
我怀疑有办法!但在 /proc
和 /sys
之外,它可能永远不会发生。无论如何,您可能希望从任何像这样的自动搜索中排除 /proc
和 /sys
-- 那里有很多魔法,所以当您开始不加选择地阅读文件时,可能会发生很多奇怪的事情。
我正在遍历我的整个文件系统,使用诸如幻数之类的标识符来寻找某些类型的文件。
我偶然发现了一些应该是 "regular" (DT_REG) 类型的文件,但是文件无法读取(read
系统调用returns 错误 38 - 系统调用未实现)。这些文件名为 "alloc_calls",位于“/sys/kernel/slab/:d-xxxxxxx/”(其中 xxxxxxx 是一个类似于 0001024 的数字)。
这是其中一个文件的 ls -l
、file
和 cat
的输出:
root@VMint:/# ls -l /sys/kernel/slab/:d-0001024/alloc_calls
-r-------- 1 root root 4096 Aug 8 18:55 /sys/kernel/slab/:d-0001024/alloc_calls
root@VMint:/# file /sys/kernel/slab/:d-0001024/alloc_calls
/sys/kernel/slab/:d-0001024/alloc_calls: ERROR: cannot read /sys/kernel/slab/:d-0001024/alloc_calls' (Function not implemented)
root@VMint:/# cat /sys/kernel/slab/:d-0001024/alloc_calls
cat: '/sys/kernel/slab/:d-0001024/alloc_calls': Function not implemented
我写了一些 C 代码来证明这一点:
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
void main()
{
char buf;
int fd = open("/sys/kernel/slab/:d-0001024/alloc_calls", 0);
perror("open");
read(fd, &buf, 1);
perror("read");
printf("fd: %d, errno: %d\n",fd, errno);
}
执行这段代码得到:
# gcc ./enosys.c -o enosys
# c_test sudo ./enosys
open: Success
read: Function not implemented
fd: 3, errno: 38
普通文件怎么会是root无法读取的呢?另外,如何识别此类文件?
/proc
和 /sys
中的文件很神奇。它们不是真正的文件——当您读写它们时,您实际上是在读写各种内核数据结构。 (mount
命令将显示它们都是挂载的文件系统,类型分别为 proc
和 sysfs
。)
对于任何存在于这些目录中的任何 "file",这意味着存在一个内核数据结构,有人认为以这种方式公开它可能有用。为了进行公开,必须设置不同的代码来实现 read()
从数据结构中获取,而 write()
存储到它。
因此,对于以这种方式公开的给定内核数据结构,如果某人实际所做的是在特定数据结构上实现(比如说)写而不是读,您会看到这样的结果。
当您调用 read()
时实际发生的是内核查找文件系统,也许还有您正在读取的单个文件,应该使用 read
的哪个设备相关实现对于那个文件。如果没有,则错误是(很自然地)ENOSYS "syscall not implemented".
Also, how can I identify such files?
我怀疑有办法!但在 /proc
和 /sys
之外,它可能永远不会发生。无论如何,您可能希望从任何像这样的自动搜索中排除 /proc
和 /sys
-- 那里有很多魔法,所以当您开始不加选择地阅读文件时,可能会发生很多奇怪的事情。