为什么Linux内核中的某些函数对字符串变量和字符串文字的工作方式不同?

时间:2017-10-08 03:06:24

标签: c linux-kernel

在Ubuntu 16.04内核版本4.4中,可加载内核模块具有以下行为:

(使用字符串文字)

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h> 
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/namei.h>
#include <linux/fs.h>

static int __init myinit(void)
{
    char *path_name = "~/microsoft.gpg";
    struct path path;

    printk("Module Init\n");

    if (kern_path(path_name, LOOKUP_FOLLOW, &path) < 0)
    {
        printk("kern_path fail\n");
        return 0;
    }
    printk("kern_path success\n");
    return 0;
}


static void __exit myexit(void)
{
    printk("Module Exit\n");
    return;
}

module_init(myinit); 
module_exit(myexit);

MODULE_LICENSE("GPL");

dmesg的结果是

  

模块初始

     

kern_path成功

(使用字符串变量)

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h> 
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/namei.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/segment.h>

#define MAX_PATH_LEN 256

static char path_name[MAX_PATH_LEN];

static struct proc_dir_entry *proc_file;

static int myopen(struct inode *inode, struct file *file)
{
    printk("Module Open\n");
    return 0;
}

static ssize_t mywrite(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
{
    struct path path;
    ssize_t bytes = count < (MAX_PATH_LEN - (*ppos)) ? count : (MAX_PATH_LEN - (*ppos));

    if (copy_from_user(path_name, user_buffer, bytes))
        return -EFAULT;

    path_name[bytes] = '\0';

    printk("Module Write\n");

    if (kern_path(path_name, LOOKUP_FOLLOW, &path) < 0)
    {
        printk("kern_path fail\n");
        (*ppos) += bytes;
        return bytes;
    }
    printk("kern_path success\n");

    (*ppos) += bytes;
    return bytes;
}

static const struct file_operations fops = 
{
    .owner = THIS_MODULE,
    .open = myopen,
    .write = mywrite,
};

static int __init myinit(void)
{
    printk("Module Init\n");
    proc_file = proc_create("mymodule", 0644, NULL, &fops);
    return 0;
}


static void __exit myexit(void)
{
    printk("Module Exit\n");
    remove_proc_entry("mymodule", NULL);
    return;
}

module_init(myinit); 
module_exit(myexit);

MODULE_LICENSE("GPL");

在shell中输入的命令是

  

echo~ / microsoft.gpg&gt;的/ proc / MyModule的

dmesg的结果是

  

模块初始

     

模块打开

     

模块写入

     

kern_path失败

在编写用户应用程序代码时我没有遇到类似的问题,但我真的很尴尬,因为内核模块存在问题。

为什么问题出现在第二个代码中?我该如何解决?

已完成答案

2 个答案:

答案 0 :(得分:1)

主要用于写入&#34;内核文件&#34;,echo命令在字符串末尾添加换行符号(这在{{中明确提到) 3}} echo}。

内核模块可以通过丢弃最后一个输入符号(如果是换行符)来轻松处理这种情况:

if(path_name[bytes - 1] == '\n')
    path_name[bytes - 1] = '\0';

答案 1 :(得分:0)

在评论中,@ Tsyvarev给了我正确答案。我传递给echo的字符串包含换行符。我把-n选项删除了。

谢谢,@ Tsyvarev!