我正在寻找一种方法来获取与任何特定内容无关的进程的唯一文件描述符。它必须是一个唯一的整数,内核不会为其创建等效的文件描述符。
到目前为止,我只是/dev/null
为了获得唯一的文件描述符编号而打开。我想知道是否有人知道实现此目的的更好方法(例如,某种“ create_fd()
”系统调用)。
在 POSIX 上:
unsigned maxfd = sysconf(_SC_OPEN_MAX);
unsigned nulfd = maxfd + 1;
注意使用,unsigned
这样我们就不会在sysconf()
返回时溢出INT_MAX
。
您可以通过 ioctl() 或使用 proc 文件创建一个模块并添加模拟文件描述符创建。文件描述符表仅存在于主管模式(在内核中)。我看不出如何在不创建新内核模块或重用恰好做你想做的事情的情况下保留它。
有关详细信息,请参见内核源代码中的fdtable.h和task_struct(进程描述符)中的files_struct 。
这是一个可以做你想做的事情的 proc 文件系统模块。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#define procfs_name "always_fail"
struct proc_dir_entry *proc_file;
int procfile_read(char *buffer,
char **buffer_location,
off_t offset, int buffer_length, int *eof, void *data)
{
printk(KERN_INFO "procfile_read (/proc/%s) called\n", procfs_name);
return -1;
}
int init_module()
{
proc_file = create_proc_entry(procfs_name, 0644, NULL);
if (proc_file == NULL) {
remove_proc_entry(procfs_name, &proc_root);
printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
procfs_name);
return -ENOMEM;
}
proc_file->read_proc = procfile_read;
proc_file->owner = THIS_MODULE;
proc_file->mode = S_IFREG | S_IRUGO;
proc_file->uid = 0;
proc_file->gid = 0;
proc_file->size = 0;
printk(KERN_INFO "/proc/%s created\n", procfs_name);
return 0;
}
void cleanup_module()
{
remove_proc_entry(procfs_name, &proc_root);
printk(KERN_INFO "/proc/%s removed\n", procfs_name);
}
阅读时应打印类似的内容:
cat /proc/always_fail
cat: /proc/always_fail: File descriptor in bad state
另一种骇人听闻的方法是简单地使用/dev/net/tun
假设您拥有它。它会在读取和写入时失败,但在打开时不会。
证明:
$ sudo strace cat /dev/net/tun
execve("/bin/cat", ["cat", "/dev/net/tun"], [/* 18 vars */]) = 0
brk(0) = 0x24c5000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f83fed22000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=128879, ...}) = 0
mmap(NULL, 128879, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f83fed02000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1848024, ...}) = 0
mmap(NULL, 3961912, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f83fe73a000
mprotect(0x7f83fe8f8000, 2093056, PROT_NONE) = 0
mmap(0x7f83feaf7000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7f83feaf7000
mmap(0x7f83feafd000, 17464, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f83feafd000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f83fed01000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f83fecff000
arch_prctl(ARCH_SET_FS, 0x7f83fecff740) = 0
mprotect(0x7f83feaf7000, 16384, PROT_READ) = 0
mprotect(0x60a000, 4096, PROT_READ) = 0
mprotect(0x7f83fed24000, 4096, PROT_READ) = 0
munmap(0x7f83fed02000, 128879) = 0
brk(0) = 0x24c5000
brk(0x24e6000) = 0x24e6000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=7220496, ...}) = 0
mmap(NULL, 7220496, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f83fe057000
close(3) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
**open("/dev/net/tun", O_RDONLY) = 3**
fstat(3, {st_mode=S_IFCHR|S_ISVTX|0666, st_rdev=makedev(10, 200), ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
**read(3, 0x24c7000, 65536) = -1 EBADFD (File descriptor in bad state)**
write(2, "cat: ", 5cat: ) = 5
write(2, "/dev/net/tun", 12/dev/net/tun) = 12
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f83fed21000
read(4, "# Locale name alias data base.\n#"..., 4096) = 2570
read(4, "", 4096) = 0
close(4) = 0
munmap(0x7f83fed21000, 4096) = 0
open("/usr/share/locale/en_CA/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en_CA/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": File descriptor in bad state", 30: File descriptor in bad state) = 30
write(2, "\n", 1
) = 1
**close(3) = 0**
close(1) = 0
close(2) = 0
exit_group(1) = ?
eric@ideapad:~$ sudo strace cat /dev/net/tun
execve("/bin/cat", ["cat", "/dev/net/tun"], [/* 18 vars */]) = 0
brk(0) = 0x109f000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdc6d3db000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=128879, ...}) = 0
mmap(NULL, 128879, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fdc6d3bb000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1848024, ...}) = 0
mmap(NULL, 3961912, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fdc6cdf3000
mprotect(0x7fdc6cfb1000, 2093056, PROT_NONE) = 0
mmap(0x7fdc6d1b0000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fdc6d1b0000
mmap(0x7fdc6d1b6000, 17464, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fdc6d1b6000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdc6d3ba000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdc6d3b8000
arch_prctl(ARCH_SET_FS, 0x7fdc6d3b8740) = 0
mprotect(0x7fdc6d1b0000, 16384, PROT_READ) = 0
mprotect(0x60a000, 4096, PROT_READ) = 0
mprotect(0x7fdc6d3dd000, 4096, PROT_READ) = 0
munmap(0x7fdc6d3bb000, 128879) = 0
brk(0) = 0x109f000
brk(0x10c0000) = 0x10c0000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=7220496, ...}) = 0
mmap(NULL, 7220496, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fdc6c710000
close(3) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
open("/dev/net/tun", O_RDONLY) = 3
fstat(3, {st_mode=S_IFCHR|S_ISVTX|0666, st_rdev=makedev(10, 200), ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, 0x10a1000, 65536) = -1 EBADFD (File descriptor in bad state)
write(2, "cat: ", 5cat: ) = 5
write(2, "/dev/net/tun", 12/dev/net/tun) = 12
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdc6d3da000
read(4, "# Locale name alias data base.\n#"..., 4096) = 2570
read(4, "", 4096) = 0
close(4) = 0
munmap(0x7fdc6d3da000, 4096) = 0
open("/usr/share/locale/en_CA/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en_CA/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": File descriptor in bad state", 30: File descriptor in bad state) = 30
write(2, "\n", 1
) = 1
close(3) = 0
close(1) = 0
close(2) = 0
exit_group(1) = ?