無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

/proc/sys/kernel/printk


/proc/sys/kernel/printkはファイルのprocfsのinod->sysctl_entryにtable["printk"]を設定し、table["printk"].proc_handlerをコール事で実装されます。引数のログレベルはスペースを区切りとし、正負および8進数/10進数/16進数の設定が可能です。/proc/sys/kernel/printkの引数は.maxlen = 4*sizeof(int)の4つですが、引数を1つとしconsole_loglevelだけ設定する事も可能で、また、syslogシステムコール様な制限はなく、minimum_console_loglevel以下のconsole_loglevelを設定でき、console_loglevel=-1とする事で、ログレベル0のKERN_EMERG等一切のシスログの画面表示を停止できます。CONFIG_PRINTKは/proc/sys/kernel/printkについてでなく、シスログその物の実装にかかるマクロです。
extern int console_printk[];

#define console_loglevel (console_printk[0])
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])

static struct ctl_table root_table[] = {
       {
               .procname       = "kernel",
               .mode           = 0555,
               .child          = kern_table,
       },
       {
               .procname       = "vm",
               .mode           = 0555,
               .child          = vm_table,
       },
       {
               .procname       = "fs",
               .mode           = 0555,
               .child          = fs_table,
       },
       {
               .procname       = "debug",
               .mode           = 0555,
               .child          = debug_table,
       },
       {
               .procname       = "dev",
               .mode           = 0555,
               .child          = dev_table,
       },
       { }
};

[root@localhost ~]# ls -l /proc/sys
合計 0
dr-xr-xr-x 0 root root 0  7月 28 23:25 crypto
dr-xr-xr-x 0 root root 0  7月 28 23:52 debug
dr-xr-xr-x 0 root root 0  7月 28 23:52 dev
dr-xr-xr-x 0 root root 0  7月 28 23:25 fs
dr-xr-xr-x 0 root root 0  7月 28 23:25 kernel
dr-xr-xr-x 0 root root 0  7月 28 23:25 net
dr-xr-xr-x 0 root root 0  7月 28 23:52 sunrpc
dr-xr-xr-x 0 root root 0  7月 28 23:52 vm

static struct ctl_table kern_table[] = {
       {
               .procname       = "sched_child_runs_first",
               .data           = &sysctl_sched_child_runs_first,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#ifdef CONFIG_SCHED_DEBUG
       {
               .procname       = "sched_min_granularity_ns",
               .data           = &sysctl_sched_min_granularity,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = sched_proc_update_handler,
               .extra1         = &min_sched_granularity_ns,
               .extra2         = &max_sched_granularity_ns,
       },
       {
               .procname       = "sched_latency_ns",
               .data           = &sysctl_sched_latency,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = sched_proc_update_handler,
               .extra1         = &min_sched_granularity_ns,
               .extra2         = &max_sched_granularity_ns,
       },
       {
               .procname       = "sched_wakeup_granularity_ns",
               .data           = &sysctl_sched_wakeup_granularity,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = sched_proc_update_handler,
               .extra1         = &min_wakeup_granularity_ns,
               .extra2         = &max_wakeup_granularity_ns,
       },
       {
               .procname       = "sched_tunable_scaling",
               .data           = &sysctl_sched_tunable_scaling,
               .maxlen         = sizeof(enum sched_tunable_scaling),
               .mode           = 0644,
               .proc_handler   = sched_proc_update_handler,
               .extra1         = &min_sched_tunable_scaling,
               .extra2         = &max_sched_tunable_scaling,
       },
       {
               .procname       = "sched_migration_cost",
               .data           = &sysctl_sched_migration_cost,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "sched_nr_migrate",
               .data           = &sysctl_sched_nr_migrate,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "sched_time_avg",
               .data           = &sysctl_sched_time_avg,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "sched_shares_window",
               .data           = &sysctl_sched_shares_window,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "timer_migration",
               .data           = &sysctl_timer_migration,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &zero,
               .extra2         = &one,
       },
#endif
       {
               .procname       = "sched_rt_period_us",
               .data           = &sysctl_sched_rt_period,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = sched_rt_handler,
       },
       {
               .procname       = "sched_rt_runtime_us",
               .data           = &sysctl_sched_rt_runtime,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = sched_rt_handler,
       },
#ifdef CONFIG_SCHED_AUTOGROUP
       {
               .procname       = "sched_autogroup_enabled",
               .data           = &sysctl_sched_autogroup_enabled,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &zero,
               .extra2         = &one,
       },
#endif
#ifdef CONFIG_CFS_BANDWIDTH
       {
               .procname       = "sched_cfs_bandwidth_slice_us",
               .data           = &sysctl_sched_cfs_bandwidth_slice,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &one,
       },
#endif
#ifdef CONFIG_PROVE_LOCKING
       {
               .procname       = "prove_locking",
               .data           = &prove_locking,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_LOCK_STAT
       {
               .procname       = "lock_stat",
               .data           = &lock_stat,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "panic",
               .data           = &panic_timeout,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "core_uses_pid",
               .data           = &core_uses_pid,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "core_pattern",
               .data           = core_pattern,
               .maxlen         = CORENAME_MAX_SIZE,
               .mode           = 0644,
               .proc_handler   = proc_dostring,
       },
       {
               .procname       = "core_pipe_limit",
               .data           = &core_pipe_limit,
               .maxlen         = sizeof(unsigned int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#ifdef CONFIG_PROC_SYSCTL
       {
               .procname       = "tainted",
               .maxlen         = sizeof(long),
               .mode           = 0644,
               .proc_handler   = proc_taint,
       },
#endif
#ifdef CONFIG_LATENCYTOP
       {
               .procname       = "latencytop",
               .data           = &latencytop_enabled,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_BLK_DEV_INITRD
       {
               .procname       = "real-root-dev",
               .data           = &real_root_dev,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "print-fatal-signals",
               .data           = &print_fatal_signals,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#ifdef CONFIG_SPARC
       {
               .procname       = "reboot-cmd",
               .data           = reboot_command,
               .maxlen         = 256,
               .mode           = 0644,
               .proc_handler   = proc_dostring,
       },
       {
               .procname       = "stop-a",
               .data           = &stop_a_enabled,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "scons-poweroff",
               .data           = &scons_pwroff,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_SPARC64
       {
               .procname       = "tsb-ratio",
               .data           = &sysctl_tsb_ratio,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef __hppa__
       {
               .procname       = "soft-power",
               .data           = &pwrsw_enabled,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "unaligned-trap",
               .data           = &unaligned_enabled,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "ctrl-alt-del",
               .data           = &C_A_D,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#ifdef CONFIG_FUNCTION_TRACER
       {
               .procname       = "ftrace_enabled",
               .data           = &ftrace_enabled,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = ftrace_enable_sysctl,
       },
#endif
#ifdef CONFIG_STACK_TRACER
       {
               .procname       = "stack_tracer_enabled",
               .data           = &stack_tracer_enabled,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = stack_trace_sysctl,
       },
#endif
#ifdef CONFIG_TRACING
       {
               .procname       = "ftrace_dump_on_oops",
               .data           = &ftrace_dump_on_oops,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_MODULES
       {
               .procname       = "modprobe",
               .data           = &modprobe_path,
               .maxlen         = KMOD_PATH_LEN,
               .mode           = 0644,
               .proc_handler   = proc_dostring,
       },
       {
               .procname       = "modules_disabled",
               .data           = &modules_disabled,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &one,
               .extra2         = &one,
       },
#endif
#ifdef CONFIG_HOTPLUG
       {
               .procname       = "hotplug",
               .data           = &uevent_helper,
               .maxlen         = UEVENT_HELPER_PATH_LEN,
               .mode           = 0644,
               .proc_handler   = proc_dostring,
       },
#endif
#ifdef CONFIG_CHR_DEV_SG
       {
               .procname       = "sg-big-buff",
               .data           = &sg_big_buff,
               .maxlen         = sizeof (int),
               .mode           = 0444,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_BSD_PROCESS_ACCT
       {
               .procname       = "acct",
               .data           = &acct_parm,
               .maxlen         = 3*sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_MAGIC_SYSRQ
       {
               .procname       = "sysrq",
               .data           = &__sysrq_enabled,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = sysrq_sysctl_handler,
       },
#endif
#ifdef CONFIG_PROC_SYSCTL
       {
               .procname       = "cad_pid",
               .data           = NULL,
               .maxlen         = sizeof (int),
               .mode           = 0600,
               .proc_handler   = proc_do_cad_pid,
       },
#endif
       {
               .procname       = "threads-max",
               .data           = &max_threads,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "random",
               .mode           = 0555,
               .child          = random_table,
       },
       {
               .procname       = "usermodehelper",
               .mode           = 0555,
               .child          = usermodehelper_table,
       },
       {
               .procname       = "overflowuid",
               .data           = &overflowuid,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &minolduid,
               .extra2         = &maxolduid,
       },
       {
               .procname       = "overflowgid",
               .data           = &overflowgid,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &minolduid,
               .extra2         = &maxolduid,
       },
#ifdef CONFIG_S390
#ifdef CONFIG_MATHEMU
       {
               .procname       = "ieee_emulation_warnings",
               .data           = &sysctl_ieee_emulation_warnings,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "userprocess_debug",
               .data           = &show_unhandled_signals,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "pid_max",
               .data           = &pid_max,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &pid_max_min,
               .extra2         = &pid_max_max,
       },
       {
               .procname       = "panic_on_oops",
               .data           = &panic_on_oops,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#if defined CONFIG_PRINTK
       {
              .procname       = "printk",   <----------------- /proc/sys/kernel/printk
              .data           = &console_loglevel,
              .maxlen         = 4*sizeof(int),
              .mode           = 0644,
              .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "printk_ratelimit",
               .data           = &printk_ratelimit_state.interval,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_jiffies,
       },
       {
               .procname       = "printk_ratelimit_burst",
               .data           = &printk_ratelimit_state.burst,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "printk_delay",
               .data           = &printk_delay_msec,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &zero,
               .extra2         = &ten_thousand,
       },
       {
               .procname       = "dmesg_restrict",
               .data           = &dmesg_restrict,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax_sysadmin,
               .extra1         = &zero,
               .extra2         = &one,
       },
       {
               .procname       = "kptr_restrict",
               .data           = &kptr_restrict,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax_sysadmin,
               .extra1         = &zero,
               .extra2         = &two,
       },
#endif
       {
               .procname       = "ngroups_max",
               .data           = &ngroups_max,
               .maxlen         = sizeof (int),
               .mode           = 0444,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "cap_last_cap",
               .data           = (void *)&cap_last_cap,
               .maxlen         = sizeof(int),
               .mode           = 0444,
               .proc_handler   = proc_dointvec,
       },
#if defined(CONFIG_LOCKUP_DETECTOR)
       {
               .procname       = "watchdog",
               .data           = &watchdog_enabled,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dowatchdog,
               .extra1         = &zero,
               .extra2         = &one,
       },
       {
               .procname       = "watchdog_thresh",
               .data           = &watchdog_thresh,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dowatchdog,
               .extra1         = &neg_one,
               .extra2         = &sixty,
       },
       {
               .procname       = "softlockup_panic",
               .data           = &softlockup_panic,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &zero,
               .extra2         = &one,
       },
       {
               .procname       = "nmi_watchdog",
               .data           = &watchdog_enabled,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dowatchdog,
               .extra1         = &zero,
               .extra2         = &one,
       },
#endif
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
       {
               .procname       = "unknown_nmi_panic",
               .data           = &unknown_nmi_panic,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#if defined(CONFIG_X86)
       {
               .procname       = "panic_on_unrecovered_nmi",
               .data           = &panic_on_unrecovered_nmi,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "panic_on_io_nmi",
               .data           = &panic_on_io_nmi,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#ifdef CONFIG_DEBUG_STACKOVERFLOW
       {
               .procname       = "panic_on_stackoverflow",
               .data           = &sysctl_panic_on_stackoverflow,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "bootloader_type",
               .data           = &bootloader_type,
               .maxlen         = sizeof (int),
               .mode           = 0444,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "bootloader_version",
               .data           = &bootloader_version,
               .maxlen         = sizeof (int),
               .mode           = 0444,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "kstack_depth_to_print",
               .data           = &kstack_depth_to_print,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "io_delay_type",
               .data           = &io_delay_type,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#if defined(CONFIG_MMU)
       {
               .procname       = "randomize_va_space",
               .data           = &randomize_va_space,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#if defined(CONFIG_S390) && defined(CONFIG_SMP)
       {
               .procname       = "spin_retry",
               .data           = &spin_retry,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#if     defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
       {
               .procname       = "acpi_video_flags",
               .data           = &acpi_realmode_flags,
               .maxlen         = sizeof (unsigned long),
               .mode           = 0644,
               .proc_handler   = proc_doulongvec_minmax,
       },
#endif
#ifdef CONFIG_IA64
       {
               .procname       = "ignore-unaligned-usertrap",
               .data           = &no_unaligned_warning,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "unaligned-dump-stack",
               .data           = &unaligned_dump_stack,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_DETECT_HUNG_TASK
       {
               .procname       = "hung_task_panic",
               .data           = &sysctl_hung_task_panic,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec_minmax,
               .extra1         = &zero,
               .extra2         = &one,
       },
       {
               .procname       = "hung_task_check_count",
               .data           = &sysctl_hung_task_check_count,
               .maxlen         = sizeof(unsigned long),
               .mode           = 0644,
               .proc_handler   = proc_doulongvec_minmax,
       },
       {
               .procname       = "hung_task_timeout_secs",
               .data           = &sysctl_hung_task_timeout_secs,
               .maxlen         = sizeof(unsigned long),
               .mode           = 0644,
               .proc_handler   = proc_dohung_task_timeout_secs,
       },
       {
               .procname       = "hung_task_warnings",
               .data           = &sysctl_hung_task_warnings,
               .maxlen         = sizeof(unsigned long),
               .mode           = 0644,
               .proc_handler   = proc_doulongvec_minmax,
       },
#endif
#ifdef CONFIG_COMPAT
       {
               .procname       = "compat-log",
               .data           = &compat_log,
               .maxlen         = sizeof (int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_RT_MUTEXES
       {
               .procname       = "max_lock_depth",
               .data           = &max_lock_depth,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       {
               .procname       = "poweroff_cmd",
               .data           = &poweroff_cmd,
               .maxlen         = POWEROFF_CMD_PATH_LEN,
               .mode           = 0644,
               .proc_handler   = proc_dostring,
       },
#ifdef CONFIG_KEYS
       {
               .procname       = "keys",
               .mode           = 0555,
               .child          = key_sysctls,
       },
#endif
#ifdef CONFIG_RCU_TORTURE_TEST
       {
               .procname       = "rcutorture_runnable",
               .data           = &rcutorture_runnable,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_PERF_EVENTS
       {
               .procname       = "perf_event_paranoid",
               .data           = &sysctl_perf_event_paranoid,
               .maxlen         = sizeof(sysctl_perf_event_paranoid),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "perf_event_mlock_kb",
               .data           = &sysctl_perf_event_mlock,
               .maxlen         = sizeof(sysctl_perf_event_mlock),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
       {
               .procname       = "perf_event_max_sample_rate",
               .data           = &sysctl_perf_event_sample_rate,
               .maxlen         = sizeof(sysctl_perf_event_sample_rate),
               .mode           = 0644,
               .proc_handler   = perf_proc_update_handler,
       },
#endif
#ifdef CONFIG_KMEMCHECK
       {
               .procname       = "kmemcheck",
               .data           = &kmemcheck_enabled,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
#ifdef CONFIG_BLOCK
       {
               .procname       = "blk_iopoll",
               .data           = &blk_iopoll_enabled,
               .maxlen         = sizeof(int),
               .mode           = 0644,
               .proc_handler   = proc_dointvec,
       },
#endif
       { }
};

[root@localhost ~]# ls -l /proc/sys/kernel/
合計 0
-rw-r--r-- 1 root root 0  7月 28 23:52 acct
-rw-r--r-- 1 root root 0  7月 28 23:52 acpi_video_flags
-rw-r--r-- 1 root root 0  7月 28 23:52 auto_msgmni
-rw-r--r-- 1 root root 0  7月 28 23:52 blk_iopoll
-r--r--r-- 1 root root 0  7月 28 23:52 bootloader_type
-r--r--r-- 1 root root 0  7月 28 23:52 bootloader_version
-rw------- 1 root root 0  7月 28 23:52 cad_pid
-r--r--r-- 1 root root 0  7月 28 23:52 cap_last_cap
-rw-r--r-- 1 root root 0  7月 28 23:25 core_pattern
-rw-r--r-- 1 root root 0  7月 28 23:25 core_pipe_limit
-rw-r--r-- 1 root root 0  7月 28 23:25 core_uses_pid
-rw-r--r-- 1 root root 0  7月 28 23:52 ctrl-alt-del
-rw-r--r-- 1 root root 0  7月 28 23:52 dmesg_restrict
-rw-r--r-- 1 root root 0  7月 28 23:52 domainname
-rw-r--r-- 1 root root 0  7月 28 23:52 ftrace_dump_on_oops
-rw-r--r-- 1 root root 0  7月 28 23:52 ftrace_enabled
-rw-r--r-- 1 root root 0  7月 28 23:52 hostname
-rw-r--r-- 1 root root 0  7月 28 23:52 hotplug
-rw-r--r-- 1 root root 0  7月 28 23:52 io_delay_type
dr-xr-xr-x 0 root root 0  7月 28 23:52 keys
-rw-r--r-- 1 root root 0  7月 28 23:52 kptr_restrict
-rw-r--r-- 1 root root 0  7月 28 23:52 kstack_depth_to_print
-rw-r--r-- 1 root root 0  7月 28 23:52 latencytop
-rw-r--r-- 1 root root 0  7月 28 23:52 max_lock_depth
-rw-r--r-- 1 root root 0  7月 28 23:52 modprobe
-rw-r--r-- 1 root root 0  7月 28 23:52 modules_disabled
-rw-r--r-- 1 root root 0  7月 28 23:52 msgmax
-rw-r--r-- 1 root root 0  7月 28 23:52 msgmnb
-rw-r--r-- 1 root root 0  7月 28 23:52 msgmni
-r--r--r-- 1 root root 0  7月 28 23:25 ngroups_max
-rw-r--r-- 1 root root 0  7月 28 23:52 nmi_watchdog
-rw-rw-rw- 1 root root 0  7月 28 23:52 ns_last_pid
-r--r--r-- 1 root root 0  7月 28 23:52 osrelease
-r--r--r-- 1 root root 0  7月 28 23:52 ostype
-rw-r--r-- 1 root root 0  7月 28 23:52 overflowgid
-rw-r--r-- 1 root root 0  7月 28 23:52 overflowuid
-rw-r--r-- 1 root root 0  7月 28 23:52 panic
-rw-r--r-- 1 root root 0  7月 28 23:52 panic_on_io_nmi
-rw-r--r-- 1 root root 0  7月 28 23:52 panic_on_oops
-rw-r--r-- 1 root root 0  7月 28 23:52 panic_on_stackoverflow
-rw-r--r-- 1 root root 0  7月 28 23:52 panic_on_unrecovered_nmi
-rw-r--r-- 1 root root 0  7月 28 23:52 perf_event_max_sample_rate
-rw-r--r-- 1 root root 0  7月 28 23:52 perf_event_mlock_kb
-rw-r--r-- 1 root root 0  7月 28 23:52 perf_event_paranoid
-rw-r--r-- 1 root root 0  7月 28 23:52 pid_max
-rw-r--r-- 1 root root 0  7月 28 23:52 poweroff_cmd
-rw-r--r-- 1 root root 0  7月 28 23:52 print-fatal-signals
-rw-r--r-- 1 root root 0  7月 29 01:08 printk
-rw-r--r-- 1 root root 0  7月 28 23:52 printk_delay
-rw-r--r-- 1 root root 0  7月 28 23:52 printk_ratelimit
-rw-r--r-- 1 root root 0  7月 28 23:52 printk_ratelimit_burst
dr-xr-xr-x 0 root root 0  7月 28 23:52 pty
dr-xr-xr-x 0 root root 0  7月 28 23:25 random
-rw-r--r-- 1 root root 0  7月 28 23:52 randomize_va_space
-rw-r--r-- 1 root root 0  7月 28 23:52 real-root-dev
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_autogroup_enabled
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_cfs_bandwidth_slice_us
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_child_runs_first
dr-xr-xr-x 0 root root 0  7月 28 23:52 sched_domain
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_latency_ns
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_migration_cost
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_min_granularity_ns
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_nr_migrate
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_rt_period_us
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_rt_runtime_us
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_shares_window
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_time_avg
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_tunable_scaling
-rw-r--r-- 1 root root 0  7月 28 23:52 sched_wakeup_granularity_ns
-rw-r--r-- 1 root root 0  7月 28 23:52 sem
-r--r--r-- 1 root root 0  7月 28 23:52 sg-big-buff
-rw-r--r-- 1 root root 0  7月 28 23:52 shm_rmid_forced
-rw-r--r-- 1 root root 0  7月 28 23:52 shmall
-rw-r--r-- 1 root root 0  7月 28 23:52 shmmax
-rw-r--r-- 1 root root 0  7月 28 23:52 shmmni
-rw-r--r-- 1 root root 0  7月 28 23:52 softlockup_panic
-rw-r--r-- 1 root root 0  7月 28 23:52 stack_tracer_enabled
-rw-r--r-- 1 root root 0  7月 28 23:25 sysrq
-rw-r--r-- 1 root root 0  7月 28 23:52 tainted
-rw-r--r-- 1 root root 0  7月 28 23:52 threads-max
-rw-r--r-- 1 root root 0  7月 28 23:52 timer_migration
-rw-r--r-- 1 root root 0  7月 28 23:52 unknown_nmi_panic
dr-xr-xr-x 0 root root 0  7月 28 23:52 usermodehelper
-r--r--r-- 1 root root 0  7月 28 23:52 version
-rw-r--r-- 1 root root 0  7月 28 23:52 watchdog
-rw-r--r-- 1 root root 0  7月 28 23:52 watchdog_thresh

static const struct file_operations proc_sys_file_operations = {
       .open           = proc_sys_open,
       .poll           = proc_sys_poll,
       .read           = proc_sys_read,
       .write          = proc_sys_write,
       .llseek         = default_llseek,
};

static ssize_t proc_sys_read(struct file *filp, char __user *buf,
                               size_t count, loff_t *ppos)
{
       return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 0);
}

static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
                               size_t count, loff_t *ppos)
{
       return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 1);
}

static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
               size_t count, loff_t *ppos, int write)
{
       struct inode *inode = filp->f_path.dentry->d_inode;
       struct ctl_table_header *head = grab_header(inode);
       struct ctl_table *table = PROC_I(inode)->sysctl_entry;
       ssize_t error;
       size_t res;

       if (IS_ERR(head))
               return PTR_ERR(head);

       error = -EPERM;
       if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
               goto out;

       error = -EINVAL;
       if (!table->proc_handler)
               goto out;

       res = count;
       error = table->proc_handler(table, write, buf, &res, ppos);
       if (!error)
               error = res;
out:
       sysctl_head_finish(head);

       return error;
}

int proc_dointvec(struct ctl_table *table, int write,
                    void __user *buffer, size_t *lenp, loff_t *ppos)
{
   return do_proc_dointvec(table,write,buffer,lenp,ppos,
                           NULL,NULL);
}

static int do_proc_dointvec(struct ctl_table *table, int write,
                 void __user *buffer, size_t *lenp, loff_t *ppos,
                 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
                             int write, void *data),
                 void *data)
{
       return __do_proc_dointvec(table->data, table, write,
                       buffer, lenp, ppos, conv, data);
}

static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
                 int write, void __user *buffer,
                 size_t *lenp, loff_t *ppos,
                 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
                             int write, void *data),
                 void *data)
{
       int *i, vleft, first = 1, err = 0;
       unsigned long page = 0;
       size_t left;
       char *kbuf;
       
       if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
               *lenp = 0;
               return 0;
       }
       
       i = (int *) tbl_data;
       vleft = table->maxlen / sizeof(*i);
       left = *lenp;

       if (!conv)
               conv = do_proc_dointvec_conv;

       if (write) {
               if (left > PAGE_SIZE - 1)
                       left = PAGE_SIZE - 1;
               page = __get_free_page(GFP_TEMPORARY);
               kbuf = (char *) page;
               if (!kbuf)
                       return -ENOMEM;
               if (copy_from_user(kbuf, buffer, left)) {
                       err = -EFAULT;
                       goto free;
               }
               kbuf[left] = 0;
       }

       for (; left && vleft--; i++, first=0) {
               unsigned long lval;
               bool neg;

               if (write) {
                       left -= proc_skip_spaces(&kbuf);

                       if (!left)
                               break;
                       err = proc_get_long(&kbuf, &left, &lval, &neg,
                                            proc_wspace_sep,
                                            sizeof(proc_wspace_sep), NULL);
                       if (err)
                               break;
                       if (conv(&neg, &lval, i, 1, data)) {
                               err = -EINVAL;
                               break;
                       }
               } else {
                       if (conv(&neg, &lval, i, 0, data)) {
                               err = -EINVAL;
                               break;
                       }
                       if (!first)
                               err = proc_put_char(&buffer, &left, '\t');
                       if (err)
                               break;
                       err = proc_put_long(&buffer, &left, lval, neg);
                       if (err)
                               break;
               }
       }

       if (!write && !first && left && !err)
               err = proc_put_char(&buffer, &left, '\n');
       if (write && !err && left)
               left -= proc_skip_spaces(&kbuf);
free:
       if (write) {
               free_page(page);
               if (first)
                       return err ? : -EINVAL;
       }
       *lenp -= left;
       *ppos += *lenp;
       return err;
}
正負および8進数/10進数/16進数の取得。
static int proc_get_long(char **buf, size_t *size,
                         unsigned long *val, bool *neg,
                         const char *perm_tr, unsigned perm_tr_len, char *tr)
{
       int len;
       char *p, tmp[TMPBUFLEN];

       if (!*size)
               return -EINVAL;

       len = *size;
       if (len > TMPBUFLEN - 1)
               len = TMPBUFLEN - 1;

       memcpy(tmp, *buf, len);

       tmp[len] = 0;
       p = tmp;
       if (*p == '-' && *size > 1) {
               *neg = true;
               p++;
       } else
               *neg = false;
       if (!isdigit(*p))
               return -EINVAL;

       *val = simple_strtoul(p, &p, 0);

       len = p - tmp;

       if (len == TMPBUFLEN - 1)
               return -EINVAL;

       if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
               return -EINVAL;

       if (tr && (len < *size))
               *tr = *p;

       *buf += len;
       *size -= len;

       return 0;
}

unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
{
       return simple_strtoull(cp, endp, base);
}

unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
{
       unsigned long long result;
       unsigned int rv;

       cp = _parse_integer_fixup_radix(cp, &base);
       rv = _parse_integer(cp, base, &result);
       cp += (rv & ~KSTRTOX_OVERFLOW);

       if (endp)
               *endp = (char *)cp;

       return result;
}

const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
{
       if (*base == 0) {
               if (s[0] == '0') {
                       if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
                               *base = 16;
                       else
                               *base = 8;
               } else
                       *base = 10;
       }
       if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
               s += 2;
       return s;
}

補足

/proc/sys下の struct ctl_table kern_table[]等のinodeを作成時、struct proc_inode *ei->sysctl_entry = tableで、掛かるファイルinodeからの参照領域の取得を実装します。
static struct inode *proc_sys_make_inode(struct super_block *sb,
               struct ctl_table_header *head, struct ctl_table *table)
{
       struct inode *inode;
       struct proc_inode *ei;

       inode = new_inode(sb);
       if (!inode)
               goto out;

       inode->i_ino = get_next_ino();

       sysctl_head_get(head);
       ei = PROC_I(inode);
       ei->sysctl = head;
       ei->sysctl_entry = table;

       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
       inode->i_mode = table->mode;
       if (!table->child) {
               inode->i_mode |= S_IFREG;
               inode->i_op = &proc_sys_inode_operations;
               inode->i_fop = &proc_sys_file_operations;
       } else {
               inode->i_mode |= S_IFDIR;
               clear_nlink(inode);
               inode->i_op = &proc_sys_dir_operations;
               inode->i_fop = &proc_sys_dir_file_operations;
       }
out:
       return inode;
}

static const struct file_operations proc_sys_dir_file_operations = {
       .read           = generic_read_dir,
       .readdir        = proc_sys_readdir,
       .llseek         = generic_file_llseek,
};

static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
       struct dentry *dentry = filp->f_path.dentry;
       struct inode *inode = dentry->d_inode;
       struct ctl_table_header *head = grab_header(inode);
       struct ctl_table *table = PROC_I(inode)->sysctl_entry;
       struct ctl_table_header *h = NULL;
       unsigned long pos;
       int ret = -EINVAL;

       if (IS_ERR(head))
               return PTR_ERR(head);

       if (table && !table->child) {
               WARN_ON(1);
               goto out;
       }

       table = table ? table->child : head->ctl_table;

       ret = 0;
       if (filp->f_pos == 0) {
               if (filldir(dirent, ".", 1, filp->f_pos,
                               inode->i_ino, DT_DIR) < 0)
                       goto out;
               filp->f_pos++;
       }
       if (filp->f_pos == 1) {
               if (filldir(dirent, "..", 2, filp->f_pos,
                               parent_ino(dentry), DT_DIR) < 0)
                       goto out;
               filp->f_pos++;
       }
       pos = 2;

       ret = scan(head, table, &pos, filp, dirent, filldir);
       if (ret)
               goto out;

       for (h = sysctl_head_next(NULL); h; h = sysctl_head_next(h)) {
               if (h->attached_to != table)
                       continue;
               ret = scan(h, h->attached_by, &pos, filp, dirent, filldir);
               if (ret) {
                       sysctl_head_finish(h);
                       break;
               }
       }
       ret = 1;
out:
       sysctl_head_finish(head);
       return ret;
}

static int scan(struct ctl_table_header *head, ctl_table *table,
               unsigned long *pos, struct file *file,
               void *dirent, filldir_t filldir)
{

       for (; table->procname; table++, (*pos)++) {
               int res;

               if (!table->procname)
                       continue;

               if (*pos < file->f_pos)
                       continue;

               res = proc_sys_fill_cache(file, dirent, filldir, head, table);
               if (res)
                       return res;

               file->f_pos = *pos + 1;
       }
       return 0;
}

static int proc_sys_fill_cache(struct file *filp, void *dirent,
                               filldir_t filldir,
                               struct ctl_table_header *head,
                               struct ctl_table *table)
{
       struct dentry *child, *dir = filp->f_path.dentry;
       struct inode *inode;
       struct qstr qname;
       ino_t ino = 0;
       unsigned type = DT_UNKNOWN;

       qname.name = table->procname;
       qname.len  = strlen(table->procname);
       qname.hash = full_name_hash(qname.name, qname.len);

       child = d_lookup(dir, &qname);
       if (!child) {
               child = d_alloc(dir, &qname);
               if (child) {
                       inode = proc_sys_make_inode(dir->d_sb, head, table);
                       if (!inode) {
                               dput(child);
                               return -ENOMEM;
                       } else {
                               d_set_d_op(child, &proc_sys_dentry_operations);
                               d_add(child, inode);
                       }
               } else {
                       return -ENOMEM;
               }
       }
       inode = child->d_inode;
       ino  = inode->i_ino;
       type = inode->i_mode >> 12;
       dput(child);
       return !!filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type);
}

static struct inode *proc_sys_make_inode(struct super_block *sb,
               struct ctl_table_header *head, struct ctl_table *table)
{
       struct inode *inode;
       struct proc_inode *ei;

       inode = new_inode(sb);
       if (!inode)
               goto out;

       inode->i_ino = get_next_ino();

       sysctl_head_get(head);
       ei = PROC_I(inode);
       ei->sysctl = head;
       ei->sysctl_entry = table;

       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
       inode->i_mode = table->mode;
       if (!table->child) {
               inode->i_mode |= S_IFREG;
               inode->i_op = &proc_sys_inode_operations;
               inode->i_fop = &proc_sys_file_operations;
       } else {
               inode->i_mode |= S_IFDIR;
               clear_nlink(inode);
               inode->i_op = &proc_sys_dir_operations;
               inode->i_fop = &proc_sys_dir_file_operations;
       }
out:
       return inode;
}

補足

proc_dointvec_minmax()はdo_proc_dointvec()でのvoid *data=NULLでなく、struct ctl_table *table->extra1/extra2の最大値/最小値をチェックするdo_proc_dointvec_minmax_convをコールバックにします。
int proc_dointvec_minmax(struct ctl_table *table, int write,
                 void __user *buffer, size_t *lenp, loff_t *ppos)
{
       struct do_proc_dointvec_minmax_conv_param param = {
               .min = (int *) table->extra1,
               .max = (int *) table->extra2,
       };
       return do_proc_dointvec(table, write, buffer, lenp, ppos,
                               do_proc_dointvec_minmax_conv, &param);
}

static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
                                       int *valp,
                                       int write, void *data)
{
       struct do_proc_dointvec_minmax_conv_param *param = data;
       if (write) {
               int val = *negp ? -*lvalp : *lvalp;
               if ((param->min && *param->min > val) ||
                   (param->max && *param->max < val))
                       return -EINVAL;
               *valp = val;
       } else {
               int val = *valp;
               if (val < 0) {
                       *negp = true;
                       *lvalp = (unsigned long)-val;
               } else {
                       *negp = false;
                       *lvalp = (unsigned long)val;
               }
       }
       return 0;
}

最終更新 2016/07/29 17:27:50 - north
(2016/07/29 16:58:07 作成)