如何在内核 space 程序中正确构建环形缓冲区?
How to correctly build a ring buffer in a kernel space program?
我正在尝试在内核 space 中编写一个带有环形缓冲区的程序,它在用户 space 上工作正常,我用 kmalloc 替换了内存分配器并得到了类型转换错误。这是用户 space:
上的程序
main ()
{
char last_char = 'a';
RingBuffer *buffer = newRingBuffer (10);
RingBuffer_trywrite (buffer, last_char);
RingBuffer_tryread(buffer, &last_char);
printf ("%s", &last_char);
return 0;
}
以下是内核space程序的部分代码:
struct RingBuffer* buffer;
static int __init ch_drv_init(void) {
buffer = newRingBuffer(BUF_CAPACITY);
}
环形缓冲区的实现取自维基百科(https://ru.wikipedia.org/wiki/Кольцевой_буфер)
请试试这个:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#define CHAR_SIZE (sizeof(char))
#define RINGBUFFER_OK (0)
#define RINGBUFFER_ERR_NULL (-1)
#define RINGBUFFER_ERR_EMPTY (-2)
#define RINGBUFFER_ERR_FULL (-3)
struct RingBuffer {
char *start;
char *end;
volatile char *readptr;
volatile char *writeptr;
};
struct RingBuffer *newRingBuffer(unsigned long int capacity)
{
struct RingBuffer *rb;
char *mem = vmalloc(capacity * CHAR_SIZE);
if (mem == NULL) {
return NULL;
}
rb = vmalloc(sizeof(*rb));
if (rb == NULL) {
vfree(mem);
return NULL;
}
rb->start = mem;
rb->end = mem + capacity;
rb->readptr = mem;
rb->writeptr = mem;
return rb;
}
void deleteRingBuffer(struct RingBuffer *rb)
{
if (rb == NULL)
return;
vfree(rb->start);
vfree(rb);
}
int RingBuffer_trywrite(struct RingBuffer *rb, char c)
{
volatile char *tmp;
if (rb == NULL)
return RINGBUFFER_ERR_NULL;
if (rb->writeptr + 1 == rb->readptr)
return RINGBUFFER_ERR_FULL;
*(rb->writeptr) = c;
tmp = rb->writeptr + 1;
if (tmp >= rb->end) tmp = rb->start;
rb->writeptr = tmp;
return RINGBUFFER_OK;
}
int RingBuffer_tryread(struct RingBuffer *rb, char *c)
{
volatile char *tmp;
if (rb == NULL)
return RINGBUFFER_ERR_NULL;
if (rb->readptr == rb->writeptr)
return RINGBUFFER_ERR_EMPTY;
*c = (*rb->readptr);
tmp = rb->readptr + 1;
if (tmp >= rb->end) tmp = rb->start;
rb->readptr = tmp;
return RINGBUFFER_OK;
}
static int __init init_test_module(void)
{
char last_char = 'a';
struct RingBuffer *buffer = newRingBuffer(10);
RingBuffer_trywrite(buffer, last_char);
RingBuffer_tryread(buffer, &last_char);
pr_info("last_char: %c\n", last_char);
deleteRingBuffer(buffer);
return 0;
}
static void __exit exit_test_module(void)
{
}
module_init(init_test_module);
module_exit(exit_test_module);
MODULE_LICENSE("GPL");
我正在尝试在内核 space 中编写一个带有环形缓冲区的程序,它在用户 space 上工作正常,我用 kmalloc 替换了内存分配器并得到了类型转换错误。这是用户 space:
上的程序main ()
{
char last_char = 'a';
RingBuffer *buffer = newRingBuffer (10);
RingBuffer_trywrite (buffer, last_char);
RingBuffer_tryread(buffer, &last_char);
printf ("%s", &last_char);
return 0;
}
以下是内核space程序的部分代码:
struct RingBuffer* buffer;
static int __init ch_drv_init(void) {
buffer = newRingBuffer(BUF_CAPACITY);
}
环形缓冲区的实现取自维基百科(https://ru.wikipedia.org/wiki/Кольцевой_буфер)
请试试这个:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#define CHAR_SIZE (sizeof(char))
#define RINGBUFFER_OK (0)
#define RINGBUFFER_ERR_NULL (-1)
#define RINGBUFFER_ERR_EMPTY (-2)
#define RINGBUFFER_ERR_FULL (-3)
struct RingBuffer {
char *start;
char *end;
volatile char *readptr;
volatile char *writeptr;
};
struct RingBuffer *newRingBuffer(unsigned long int capacity)
{
struct RingBuffer *rb;
char *mem = vmalloc(capacity * CHAR_SIZE);
if (mem == NULL) {
return NULL;
}
rb = vmalloc(sizeof(*rb));
if (rb == NULL) {
vfree(mem);
return NULL;
}
rb->start = mem;
rb->end = mem + capacity;
rb->readptr = mem;
rb->writeptr = mem;
return rb;
}
void deleteRingBuffer(struct RingBuffer *rb)
{
if (rb == NULL)
return;
vfree(rb->start);
vfree(rb);
}
int RingBuffer_trywrite(struct RingBuffer *rb, char c)
{
volatile char *tmp;
if (rb == NULL)
return RINGBUFFER_ERR_NULL;
if (rb->writeptr + 1 == rb->readptr)
return RINGBUFFER_ERR_FULL;
*(rb->writeptr) = c;
tmp = rb->writeptr + 1;
if (tmp >= rb->end) tmp = rb->start;
rb->writeptr = tmp;
return RINGBUFFER_OK;
}
int RingBuffer_tryread(struct RingBuffer *rb, char *c)
{
volatile char *tmp;
if (rb == NULL)
return RINGBUFFER_ERR_NULL;
if (rb->readptr == rb->writeptr)
return RINGBUFFER_ERR_EMPTY;
*c = (*rb->readptr);
tmp = rb->readptr + 1;
if (tmp >= rb->end) tmp = rb->start;
rb->readptr = tmp;
return RINGBUFFER_OK;
}
static int __init init_test_module(void)
{
char last_char = 'a';
struct RingBuffer *buffer = newRingBuffer(10);
RingBuffer_trywrite(buffer, last_char);
RingBuffer_tryread(buffer, &last_char);
pr_info("last_char: %c\n", last_char);
deleteRingBuffer(buffer);
return 0;
}
static void __exit exit_test_module(void)
{
}
module_init(init_test_module);
module_exit(exit_test_module);
MODULE_LICENSE("GPL");