【问题标题】:errno: 38 (Function not implemented) on a call to change sysctl valueerrno:38(功能未实现)调用更改 sysctl 值
【发布时间】:2013-07-24 14:04:43
【问题描述】:

我想用我的程序设置一些本地 sysctl 参数,我按照这里给出的说明进行操作:http://www.linux.it/~rubini/docs/sysctl/

作为示例,我正在为/proc/sys/net/ipv6/conf/tun0/accept_ra 设置值。我刚刚在此调用之前配置了我的tun0 接口。 (我确认我的接口已经启动,并且我也可以分配一个 IP 地址)

int path_len = 5;
int tun0_accept_ra_path[] =  { CTL_NET,
                               NET_IPV6,
                               NET_IPV6_CONF,
                               ifr6.ifr6_ifindex, // This ifindex comes from an interface configured above
                               NET_IPV6_ACCEPT_RA };
int tun0_accept_ra_value = 0;
if (sysctl(tun0_accept_ra_path,
           path_len,
           NULL,
           0,
           &tun0_accept_ra_value,
           sizeof(tun0_accept_ra_value)) < 0) {
  printf("set sysctl 'accept_ra' failed. errno: %d\n", errno);
}

我得到:set sysctl 'accept_ra' failed. errno: 38 Function not implemented

对可能出现的问题有任何想法吗?我以 sudo 运行,所以我认为我不应该有访问权限问题。

我在树莓派上运行 Debian GNU/Linux 7.0 (wheezy)。

【问题讨论】:

  • 引用我的手册页:“Glibc 没有为这个系统调用提供包装器;使用syscall(2) 调用它。或者更确切地说......不要调用它:长期以来一直不鼓励使用这个系统调用,它非常不受欢迎,很可能在未来的内核版本中消失。从 Linux 2.6.24 开始,使用这个系统调用会导致内核日志中出现警告。从你的现在程序;改用 /proc/sys 接口。这个系统调用只有在内核配置了 CONFIG_SYSCTL_SYSCALL 选项时才可用。"
  • 谢谢!错过这个感觉很傻,但我很高兴我现在知道了。

标签: c linux ipv6 errno sysctl


【解决方案1】:

你用的教程太老了!如果你想要这个系统调用的参考,你应该查看这个链接:http://man7.org/linux/man-pages/man2/sysctl.2.html

您收到 SIGSYS 错误,因为 sysctl 不存在。该系统的正确名称是 *_syscall* 并且 glibc 不提供包装器,因为不应调用此系统调用(它将从下一个 Linux 版本中删除)。您可以使用 /proc 接口获得相同的结果。

如果你想保留你的解决方案,你应该改变代码如下(我没有测试,对不起):

#include <sys/syscall.h> 

int path_len = 5;
int tun0_accept_ra_path[] =  { CTL_NET,
                               NET_IPV6,
                               NET_IPV6_CONF,
                               ifr6.ifr6_ifindex, 
                               NET_IPV6_ACCEPT_RA };
int tun0_accept_ra_value = 0;
if (syscall(__NR_sysctl, 
           tun0_accept_ra_path,
           path_len,
           NULL,
           0,
           &tun0_accept_ra_value,
           sizeof(tun0_accept_ra_value)) < 0) {
  printf("set sysctl 'accept_ra' failed. errno: %d\n", errno);
}

更好的解决方案可能是:

int tun0_accept_ra_value = 0;

if ((fd=open("/proc/sys/net/ipv6/conf/tun0/accept_ra", O_RDWR)) < 0) 
   perror("OPEN"); 

if (write (fd, &tun0_accept_ra_value, sizeof(int)) < 0)
   perror("WRITE"); 

close(fd); 

我希望我有用。

【讨论】:

  • 非常感谢!我应该检查一下不鼓励使用这个系统调用。我现在只是直接写入文件,效果很好。我可能还会在那里使用 O_TRUNC 标志来确保覆盖。
猜你喜欢
  • 2011-03-19
  • 2023-03-13
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-17
  • 2012-06-29
  • 1970-01-01
相关资源
最近更新 更多