OS/Linux

kernel write test code

아르비스 2010. 5. 25. 15:54


#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>   //copy_to_user()

#define BUFF_SIZE 1024
#define MAJOR_NUMBER 250
#define DEVICE_NAME "mydev"

struct kthread_t
{
  struct task_struct *thread;
  int running;
};

struct kthread_t *kthread_w = NULL;
struct kthread_t *kthread_r = NULL;

static struct workqueue_struct *my_wq;

static char *buffer = NULL;
static int sz_data =0;

static int Major;
static int Device_open = 0;
static char *msg_Ptr;
static char msg[80];


static int write_thread(void *unused);
static int read_thread(void *unused);

static DECLARE_WORK(write_wq,(void *)write_thread);
static DECLARE_WORK(read_wq,(void *)read_thread);

static int my_open( struct inode *inode, struct file *filp );
static int my_release( struct inode *inode, struct file *filp );
static ssize_t my_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos );
static ssize_t my_read( struct file *filp, char *buf, size_t count, loff_t *f_pos );

static struct file_operations vd_fops = {
  .read = my_read,
  .write = my_write,
  .open = my_open,
  .release = my_release
};


int queue_module_init(void)
{
  int ret;

 Major = register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &vd_fops);
 printk(KERN_ALERT "mknod /dev/%s c %d 0.'n", DEVICE_NAME, Major);
  
 buffer = (char*) kmalloc( BUFF_SIZE, GFP_KERNEL );
 memset( buffer, 0, BUFF_SIZE );
 printk( "Virtual device Initialized\n");

  my_wq = create_workqueue("my_queue");
  if (my_wq)
  {
   /* Queue some work (item 1) */
   if(1)
  {
   printk(" Write thread create \n");
   ret = queue_work( my_wq, &write_wq);
  }

   /* Queue some work (item 2) */
  if(1)
  {
   printk(" Read thread create \n");
   ret = queue_work( my_wq, &read_wq );
  }
  }

 sprintf(msg, "Device open\n");
 msg_Ptr = msg;
 try_module_get(THIS_MODULE);
 
  return 0;
}

int queue_module_exit(void)
{

 /*
  * Unregister the device
  */
 unregister_chrdev(MAJOR_NUMBER, DEVICE_NAME);

 kfree( buffer );
 printk( "Virtual device exited\n");
 
   printk(" Write Thread stop \n");
   printk(" Read Thread stop \n");

  flush_workqueue( my_wq );
  destroy_workqueue( my_wq );

  module_put(THIS_MODULE);

  return 0;
}

static int my_open( struct inode *inode, struct file *filp )
{
  printk( "Virtual Buffer opened\n" );
  return 0;
}

static int my_release( struct inode *inode, struct file *filp )
{
  printk( "Virtual Buffer released\n" );
  return 0;
}

static ssize_t my_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos )
{
   printk( "Virtual Buffer write to buffer\n");

   if (BUFF_SIZE < count)  sz_data  = BUFF_SIZE;
                           sz_data  = count;

   strncpy( buffer, buf, sz_data);
   return count;
}

static ssize_t my_read( struct file *filp, char *buf, size_t count, loff_t *f_pos )
{
 int byte_read = 0;

 if(*msg_Ptr ==0 )
  return 0;

 while (count && *msg_Ptr)
 {
  put_user(*(msg_Ptr++), buffer++);

  count--;
  byte_read++;
 }
 
  printk( "Virtual read from buffer\n" );

  return byte_read;
}

static int write_thread(void *unused)
{
 int  fd;
 char *str_thread  = "Write thread[%d]\n";
 char *str;
 char *time;
 int i=0;
 
 while( i < 10)
 {
     msleep_interruptible(1000);
     if(kthread_should_stop())
        break;

  printk(KERN_ALERT "write thread\n");
/*
  if ( 0 < ( fd = open( "/dev/virtual_buffer", O_RDWR)))
  {
   // init string
   sprintf(str,str_thread,i);

   if (str[0] =! NULL)
   {
    // write string
    write( fd, str, strlen(str)+1); // +1: Include NULL
    printk(KERN_ALERT "write thread [%d] \n", i);
   }
   close( fd);
  }
*/
 }
 
 return 0;
}

static int read_thread(void *unused)
{
 int  fd;
 char buff[BUFF_SIZE];

 printk(KERN_ALERT "read thread\n");
/*
 if ( 0 < ( fd = open( "/dev/virtual_buffer", O_RDWR)))
 {
     msleep_interruptible(1000);
     if(kthread_should_stop())
       break;

  memset(buff, 0x0, BUFF_SIZE);
  
  read(fd, buff, BUFF_SIZE);
  printk(KERN_ALERT "Read thread from virtual buffer\n");

  printf( "\n%s\n", buff);

  close(fd);
 }
*/
    return 0;
}

module_init(queue_module_init);
module_exit(queue_module_exit);

MODULE_LICENSE("GPL");