Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 159 additions & 11 deletions test.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/kfifo.h>

MODULE_DESCRIPTION("My kernel module");
MODULE_AUTHOR("Me");
Expand All @@ -14,31 +17,169 @@ MODULE_LICENSE("GPL");
#define DUMMY_NUM_MINORS 1
#define DUMMY_MODULE_NAME "dummy"

#define MAX_LENGTH_MSG 512 //511 + '\0'

static DEFINE_MUTEX(read_lock);
static DEFINE_MUTEX(write_lock);

int openCount = 0;
int closeCount = 0;

struct dummy_device_data {
struct cdev cdev;
dev_t dev;
};

static struct dummy_device_data dummy_device_data[DUMMY_NUM_MINORS];
struct fifo_cell
{
struct fifo_cell* next_cell;
char msg[MAX_LENGTH_MSG];
};

struct dummy_fifo
{
struct fifo_cell* start;
struct fifo_cell* end;
} fifo;

/**
* Если очередь пуста, то вернет 1, иначе 0
*/
int isFifoEmpty (struct dummy_fifo* fifo){
if ( (fifo->start == NULL) && (fifo->end == NULL))
{
return 1;
}else
return 0;
}

void AddMsgToFifo( char msg[MAX_LENGTH_MSG - 1], struct dummy_fifo* fifo){
struct fifo_cell *new_cell = kmalloc( sizeof( struct fifo_cell), GFP_KERNEL);
new_cell -> next_cell = NULL;
strcpy( new_cell->msg, msg);

static int dummy_open(struct inode *inode, struct file *file)
if( isFifoEmpty( fifo) )
{
fifo->start = new_cell;
fifo->end = new_cell;
}else
{
new_cell->next_cell = fifo->end;
fifo->end = new_cell;
}

}

/**
* Вытаскивает сообщение из очереди и печатает его. Если очередь пуста, то вернет 1
* UPD: Странное поведние, если возвращает не 0. Так что пусть всегда вернет 0
*/
int GetMsgFromFifo( struct dummy_fifo* fifo)
{
printk("%s: opened.\n", DUMMY_MODULE_NAME);
if ( isFifoEmpty( fifo))
{
printk(KERN_INFO "[ALERT] Fifo is empty. Nothing to read\n");
return 0;
}
/* Случай, когда 1 элемент в очереди */
if (fifo->start == fifo->end)
{
printk(KERN_INFO "[MESSAGE] %s\n", fifo->start->msg);
kfree(fifo->start);
fifo->start = NULL;
fifo->end = NULL;
return 0;
}else
/* Случай, когда в очереди >1 элемента */
{
struct fifo_cell *cell = fifo->start;
struct fifo_cell *prev_cell = fifo->end;

while(prev_cell->next_cell != cell)
{
prev_cell = prev_cell->next_cell;
}

printk(KERN_INFO "[MESSAGE] %s\n", cell->msg);
kfree(cell);
fifo->start = prev_cell;
prev_cell->next_cell = NULL;
return 0;
}
}


/* Буфер и размер данных для записи в него */
static char driver_buffer[MAX_LENGTH_MSG];
static unsigned long driver_buffer_size = 0;


static struct kfifo test;
static struct dummy_device_data dummy_device_data[DUMMY_NUM_MINORS];

ssize_t dummy_read (struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
int ret;
unsigned int copied;

if (mutex_lock_interruptible(&read_lock))
return -ERESTARTSYS; //Необходимо для перезапуска процесса записи, если mutex кем-то захвачен

ret = GetMsgFromFifo( &fifo);

mutex_unlock(&read_lock);

return ret;
}

ssize_t dummy_write (struct file *file, const char __user *buffer, size_t len, loff_t *off)
{
if (mutex_lock_interruptible(&write_lock))
return -ERESTARTSYS; //Необходимо для перезапуска процесса записи, если mutex кем-то захвачен


if ( len > MAX_LENGTH_MSG - 1 ) {
driver_buffer_size = MAX_LENGTH_MSG - 1;
}
else {
driver_buffer_size = len;
}

if ( copy_from_user(driver_buffer, buffer, driver_buffer_size) ) {
return -EFAULT;
}

AddMsgToFifo( driver_buffer, &fifo);

printk(KERN_INFO "[INFO] writed %lu bytes\n", driver_buffer_size);

mutex_unlock(&write_lock);

return driver_buffer_size;
}

static int dummy_release (struct inode *inode, struct file *file)

int dummy_open (struct inode *pinode, struct file *pfile)
{
printk("%s: closed.\n", DUMMY_MODULE_NAME);
openCount++;
printk(KERN_ALERT "[OPENING] It has been opened %d times\n", openCount);
return 0;
}


int dummy_close (struct inode *pinode, struct file *pfile)
{
closeCount++;
printk(KERN_ALERT "[CLOSING] It has been closed %d times\n", closeCount);
return 0;
}

static struct file_operations dummy_fops = {
.owner = THIS_MODULE,
.open = dummy_open,
.release = dummy_release
struct file_operations dummy_fops = {
.owner = THIS_MODULE,
.read = dummy_read,
.write = dummy_write,
.open = dummy_open,
.release = dummy_close
};

static int dummy_chrdev_init(void)
Expand Down Expand Up @@ -108,13 +249,20 @@ static int dummy_init(void)
__FUNCTION__, error);
}

return 0;

/* Initializing fifo */
fifo.start = NULL;
fifo.end = NULL;

return 0;
}

static void dummy_exit(void)
{
printk("%s: Bye\n", __FUNCTION__);
printk(KERN_ALERT "[EXITING]\n");
kfree(&fifo);
}


module_init(dummy_init);
module_exit(dummy_exit);