首页 > 解决方案 > 在 Linux 上使用 C 语言调用 sysctl() 的示例

问题描述

我已经阅读了一些关于在 C 中使用 sysctl() 调用的警告,似乎如果我不能安全地使用 sysctl(),我能找到的唯一另一种方法是使用类似的东西:

system("echo  fs.inotify.max_user_watches=NEW_MAX_DIRECTORIES  >> /etc/sysctl.conf");
system("sysctl -p");

(当然,这假设确保二进制文件以 root 身份运行。但是,我宁愿不必使用系统调用来解决问题。

有人可以指出使用 sysctl() 的正确和安全吗?

这是我正在使用的代码片段。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>        
int main ()
{
        int ret;
        const char *LOGNAME="iNotifyMonitor";
        logger(INFO, "================================================");
        ret = startDaemon();
        daemonRunning = ret;

        if (ret == 0)
        {
                daemonRunning = 1;
                FIRST_RUN = 0;
        }

        if(ret)
        {
                syslog(LOG_USER | LOG_ERR, "Error starting iNotifyMonitor");
                logger(ERR, "Unable to start iNotifyMonitor");
                closelog();
                return EXIT_FAILURE;
        }

        signal(SIGINT, signalHandler);
        signal(SIGHUP, signalHandler);
        char *log_file_name = malloc(sizeof(char *) * sizeof(char *));
        sprintf(log_file_name, "%s%s", INM_LOG_DIR, INM_LOG_FILE);
        /* Try to open log file to this daemon */
        if (INM_OPEN_LOG && INM_LOG_FILE)
        {
        log_stream = fopen(concatString(INM_LOG_DIR, INM_LOG_FILE), "a+");
                if (log_stream == NULL)
                {
                        char *errMsg;
                        sprintf(errMsg, "Cannot open log file %s, error: %s", concatString(INM_LOG_DIR, INM_LOG_FILE), strerror(errno));
            log_stream = stdout;
        }
        }
        else
        {
                log_stream = stdout;
    }

    while (daemonRunning == 1)
        {
        if (ret < 0)
                {
            logger(LOG_ERR, "Can not write to log stream: %s, error: %s", (log_stream == stdout) ? "stdout" : log_file_name, strerror(errno));
                        break;
                }
                ret = fflush(log_stream);
                if (ret != 0)
                {
                logger(LOG_ERR, "Can not fflush() log stream: %s, error: %s",
                                (log_stream == stdout) ? "stdout" : log_file_name, strerror(errno));
                        break;
                }
                int curcount =countDirectory("/home/darrinw/Development/CrossRoads/");
                directoryCount = curcount;
                if(directoryCounrt > INM_MAX_DIRECTORIES)
                {
                        int newVal = roundUp(directoryCount, 32768);

                        // call to sysctl() to modify fs.inotify.max_users_watches=newVal
                }


        sleep(INM_SCAN_INTERVAL);
        }

标签: clinuxsysctl

解决方案


我的理解是,现代推荐的访问 sysctl 变量的方法是通过/proc/sys. 所以只要打开/proc/sys/fs/inotify/max_user_watches并在那里写。

int fd = open("/proc/sys/fs/inotify/max_user_watches", O_WRONLY);
dprintf(fd, "%d", NEW_MAX_DIRECTORIES);
close(fd);

错误检查留作练习。

修改/etc/sysctl.conf将使设置在重新启动后保持不变(假设您的发行版以这种方式使用该文件,我不确定它们是否都这样做)。自动这样做有点粗鲁。如果需要,最好使用文档来建议系统管理员自己做。


推荐阅读