在linux中通信和同步内核和用户空间的最佳方式

时间:2010-12-15 10:04:35

标签: linux-kernel device-driver kernel kernel-module

我的目标是从内核记录很多活动。为此,我需要写入基于磁盘的文件系统。

因此,我实现了一个字符设备驱动程序,以及一个从该虚拟设备读取的用户空间进程。驱动程序将数据复制到用户空间缓冲区,用户进程将其写入文件。

我的问题是如何同步数据。我开始在fifo的内核实现中使用kfifo。因此,无论我想记录哪里,我都使用kfifo API将数据复制到fifo中。虚拟设备驱动程序从fifo读取并将其复制到用户空间。由于记录的数据很大,我需要同步,例如在生产者消费者中。我可以使用linux内核中有这样的支持吗?

netlink socket是否解决了这个问题?

3 个答案:

答案 0 :(得分:0)

您可能想要使用中继接口,请参阅Documentation/filesystems/relay.txt

答案 1 :(得分:0)

我认为netlink套接字比char设备更能满足您的需求。内核将在它想要写入时写入套接字,并且将在此套接字上等待的用户程序将从中读取并将其写入文件。

此外,如果您只是尝试从内核记录某些内容以获取某些信息而不是编写模块或更改Linux内核以供生产使用,那么从内核中打开和写入文件会更简单,更快速(如开发时间) )。

答案 2 :(得分:0)

如果要记录大量数据并且不想错过任何日志数据,也可以使用简单的双缓冲原则。

我不确定kfifo,但是在你的角色设备驱动程序的读取调用中,如果没有要从设备读取的数据,则可以将用户空间进程置于休眠状态。每当内核写入字符设备时,它就会唤醒在设备上休眠的任何进程。例如,

In kernel
 struct logbufStruct {
   char *kbuf; //by kmalloc or any means you wish.
   int ptr; //ptr to next writeable byte in kbuf.
   size_t kbuf_size;
   unsigned int flags;
   wait_queue_head_t data_wait;
 }
 read(inode, filep, buf, size) {
  logbufStruct = filep->private_data
  if (!test_bit(HAS_DATA, &logbufstruct.flags))
    wait_event_interruptible(&logbufstruct->data_wait, 
           test_bit(HAS_DATA, &logbufstruct.flags)||
           test_bit(ERROR, &logbufstruct.flags));
  /*
   * When this call returns, you would either have woken up
   * on data available or some signal interrupt which you should
   * handle in your character device and set appropriate flags.
   */
    if (test_bit(ERROR, &logbufstruct.flags) return -1;
    numbytes = copy_data(logbufStruct, buf, size);
    if(!has_more_data(logbufstruct)) clear_bit(HAS_DATA, &logbufstruct.flags);
    return numbytes;
 }

 /* This is the function your modules would call to log data
  * to be sent to userspace.
  */
 int mylogger_log(logbufstruct, char *msg, size_t n)
 {
   if (logbufstruct->ptr + n > logbufstruct->kbuf_size)
      return -1;
   copy the data.
   wake_up_interruptible(&logbufstruct->data_wait);
 }
 //initialization
  init_waitqueue_head(&logbufstruct->data_wait);
  logbufstruct->kbuf = kmalloc or whatever way you have to allocate
   space for holding log messages in memory.