linux - 从 perl 执行挂载系统调用

标签 linux perl system-calls mount

如何从 perl 完成 mount 系统调用?以下内容:

$ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0);

结果:

Modification of a read-only value attempted at ...

我无法使用 system 调用 mount 程序,因为我需要进行 mount() 系统调用,mount 程序似乎没有能力。更具体地说,我需要调用:

mount("/proc", "/path/to/my/mpoint/point", NULL, MS_REC|MS_PRIVATE|MS_BIND, NULL);

但是如果我尝试使用非特权非共享挂载 linux 命名空间运行以下命令:

mount --make-rprivate --bind /proc /path/to/my/mountpoint

然后我得到以下错误:

mount: wrong fs type, bad option, bad superblock on /proc,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.

使用 strace 显示 mount 程序实际做的是调用:

mount("/proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND, NULL);
mount("none", "/path/to/my/mointpoint", NULL, MS_REC|MS_PRIVATE, NULL);

但是这种拆分选项不起作用。我需要在对 mount 系统调用的单个调用中使用 MS_BINDMS_REC|MS_PRIVATE 以使其在非特权非共享装载命名空间中工作。

那么我怎样才能在 perl 中执行我的初始系统调用而不出现有关尝试修改只读值的错误消息呢?

编辑:

谢天谢地,ikegami 很快指出了我在尝试使用 perl 的 syscall 函数时做错了什么,但以防万一有人在搜索如何从非特权挂载命名空间中绑定(bind)挂载目录时发现这一点只是 mount 命令行实用程序,方法如下:

mount --rbind /proc /path/to/my/mountpoint

这将在内部调用以下系统调用:

mount("proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND|MS_REC, 0);

MS_MGC_VAL 标志似乎只是为了向后兼容 2.4 之前的内核版本。重要的位是 MS_BIND(用于自己进行绑定(bind)挂载)和 MS_REC(用于递归执行此操作,以便其内容被其他挂载隐藏的目录执行到它们中)没有在挂载命名空间中公开它们的内容)。

所以现在我必须决定是使用 perl system 函数调用还是只执行 mount 系统调用,因为两者都一样有效:)

最佳答案

syscall拒绝传递指向常量字符串缓冲区的指针,因为它不知道参数是 char * 还是 const char *

You can't use a string literal (or other read-only string) as an argument to syscall because Perl has to assume that any string pointer might be written through

解决方法很简单。只需先将常量复制到变量中即可。

my $ret = syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0);

测试:

$ perl -E'
   require "syscall.ph";
   my $ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0);
   say $ret;
'
Modification of a read-only value attempted at -e line 3.

$ perl -E'
   require "syscall.ph";
   my $ret = syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0);
   say $ret;
'
-1

$ strace perl -e'
   require "syscall.ph";
   syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0);
' 2>&1 | grep mount
mount("/proc", "/path/to/my/mount/point", NULL, 0, NULL) = -1 ENOENT (No such file or directory)

关于linux - 从 perl 执行挂载系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33263510/

相关文章:

c - 调用 open 时如何调用 sys_open 而不是 sys_openat

regex - 在Perl正则表达式中嵌入评估

python - 关闭 Python 守护进程时运行代码

linux - 未检测到支持 CUDA 的设备(使用 ubuntu 12.04.4 服务器)

python - 对于 python 初学者来说,自动化流程的一些很好的例子是什么?

linux - 将 perl 结果输出到文件中

linux - 我如何使用 perl cd 进入一个目录?

c - 如何检查内存区域是否映射到文件?

c - 系统调用超时?

c - 如何在 sync/fsync/syncfs 到可移植设备后确保数据完整性