【问题标题】:I need help in understanding the following kernel module written in C [closed]我需要帮助来理解以下用 C 编写的内核模块 [关闭]
【发布时间】:2016-01-10 11:16:25
【问题描述】:

作为一项作业,我需要完成以下 C 代码,以生成能够充当内存的内核模块,但从它的编写方式来看,我无法理解它是如何工作的,以及为什么没有使用许多变量,而只是宣布。我已经尝试过查看他们给我的教材,这更加令人困惑,而且我在网上找不到一个很好的网站来找到有关这些功能的文档。

代码如下:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#define DEVICE_NAME             "my_device"
#define MAJOR_DEVICE_NUMBER     60
#define MINOR_DEVICE_NUMBER     0
#define BUF_LEN                 1024

static char msg[BUF_LEN];
static char *msg_ptr; // I'm pretty sure this should become msg_reading_offset
static int major;

MODULE_AUTHOR("<YOUR NAME>");
MODULE_LICENSE("GPL");

static ssize_t my_read (
    struct file *filp, char __user *buf,
    size_t length, loff_t *offset);
static ssize_t my_write (
    struct file *filp, const char __user *buf,
    size_t length, loff_t *offset);
static int my_open (struct inode *inode,
    struct file *filp);
static int my_close (struct inode *inode,
    struct file *filp);
static int __init my_init (void);
static void __exit my_cleanup (void);
static struct file_operations fops = {
    .read = my_read,
    .write = my_write,
    .open = my_open,
    .release = my_close,
};

// I need to implement this function
static int my_open (struct inode *inode,
   struct file *filp)
{
    return 0;
}
// and this function
static int my_close (struct inode *inode,
    struct file *filp)
{
    return 0;
}

static ssize_t my_read (
    struct file *filp, char __user *buf,
    size_t length, loff_t *offset)
{
   int nc = 0;
   // if no more "valid" bytes can be read, stop
   if (*msg_reading_offset == 0) return 0;
   // no-negative values allowed
   if (length < 0)
      return -EINVAL;
   // read the whole msg, nothing more
   if (length > strlen(msg)) {
       length = strlen(msg);
   }
   nc = copy_to_user(buf, msg_reading_offset, length);
   /*
   updates the current reading offset pointer so that a
   recursive call due to not original
   full length will get a 0 (nothing to read)
   */
   msg_reading_offset += sizeof(char) * (length-nc);
   // returns the number of REAL bytes read.
   return length - nc;
}

static ssize_t my_write (
    struct file *filp, const char __user *buf,
    size_t length, loff_t *offset)
{
   int nc = 0;
   if (length > BUF_LEN)
      return BUF_LEN-length;
   nc = copy_from_user(msg,buf,length);
   msg_ptr = msg;
   return length - nc;
}

static int __init my_init (void)
{
   register_chrdev (MAJOR_DEVICE_NUMBER,
      DEVICE_NAME,
      &fops);

}
module_init(my_init);
static void __exit my_cleanup (void)
{
   unregister_chrdev (major, DEVICE_NAME);
}
module_exit(my_cleanup);

目前这些是我最大的问题:

  • *inode、*filp 变量都去哪儿了?我应该使用它们吗?
  • 这个程序是如何工作的?我知道我需要用我得到的 makefile 来编译它,但是我应该如何访问这些函数呢?
  • 这应该是由内核执行的真实程序,还是只是我应该在另一个 C 程序中使用的函数集合?

如果这些问题看起来很愚蠢,我很抱歉,但我不知道我应该如何解决这个问题。

【问题讨论】:

  • 太宽泛了。 SO 不是“解释代码”网站。
  • 第一步是了解内核模块是什么。这应该可以清除一堆东西。
  • @Mat 这就是我过去 2 天一直在尝试做的事情。
  • @Olaf 我应该编辑它还是有这样一个“解释代码”的网站?
  • 您阅读了哪些有关 Linux 内核模块的书籍和网站?

标签: c linux kernel


【解决方案1】:

你的问题有点宽泛,但我会尽量给你一些提示。

*inode、*filp 变量都去哪儿了?我应该使用它们吗?

首先阅读一个典型字符设备是如何实现的示例,例如here

这个程序是如何工作的?我知道我需要使用给定的 makefile 来编译它,但是我应该如何访问这些函数呢?

这应该是由内核执行的真实程序还是只是我应该在另一个 C 程序中使用的函数集合?

这不是一个正常的可执行程序。在编写内核模块时,您正在扩展内核功能。你需要告诉内核这件事,通常是通过insmod 调用。例如,

insmod chardev.ko

然后创建对应的字符设备:

mknod /dev/chardev c 60 0    # 60 being your MAJOR_DEVICE_NUMBER

然后您可以创建自己的程序到readwrite 到您的字符设备。或者,您可以使用现有的用户空间工具:

echo "12345678" > /dev/chardev    # write to the device

和,

cat /dev/chardev    # read from the device

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 2023-03-14
    • 2012-02-02
    • 2015-12-09
    • 2011-05-04
    相关资源
    最近更新 更多