본문 바로가기
실습/리눅스 커널

Kernel Module - template

by 써드아이 2021. 2. 8.

[블로그 통합으로 이전해 온 자료] - 2008. 4. 24. 02:24

 

 

%% LDD 3판에서 따옴

loaddev - 드라이버를 로드하고 nod 파일을 만든다.

#!/bin/sh
MODULE="template"
DEVICE="template"
MODE="664"

if grep -q '^staff:' /etc/group; then
 GROUP="staff"
else
 GROUP="wheel"
fi

/sbin/insmod $MODULE.ko $* || exit 1

MAJOR=$(awk "\$2==\"$MODULE\" " /proc/devices)

rm -rf /dev/$[0-3]
mknod /dev/$0 c $MAJOR 0
mknod /dev/$1 c $MAJOR 0
mknod /dev/$2 c $MAJOR 0
mknod /dev/$3 c $MAJOR 0
ln -sf $0 /dev/$
chgrp $GROUP /dev/$[0-3]
chmod $MODE /dev/$[0-3]

 

 

unloaddev - 드라이버 언로드

#!/bin/sh
MODULE="template"
DEVICE="template"
/sbin/rmmod $MODULE $* || exit

 

 

Makefile

ifneq ($(KERNELRELEASE),)
template-objs :=  main.o utils.o proc.o
obj-m := template.o

else
KERNELDIR ?= /opt/arm9sbc/ahav/kernel/linux-2.6.22.8
PWD := $(shell pwd)

modules:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

clean:
 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.symvers

 

 

template.h

#ifndef __TEMPLATE_H__
#define __TEMPLATE_H__
#include <linux/ioctl.h>

#define TEMPLATE_MAJOR    0
#define TEMPLATE_NR_DEVS   4

extern int template_major;    // template_main.c
extern int template_nr_devs;

void template_create_proc( void );
void template_remove_proc( void );

#define TEMPLATE_IOC_MAGIC    'k'

#define TEMPLATE_IOCRESET    _IO(TEMPLATE_IOC_MAGIC, 0)

#define TEMPLATE_IOCSQUANTUM   _IOW(TEMPLATE_IOC_MAGIC, 1, int)
#define TEMPLATE_IOCSQSET    _IOW(TEMPLATE_IOC_MAGIC, 2, int)
#define TEMPLATE_IOCTQUANTUM   _IO(TEMPLATE_IOC_MAGIC, 3)
#define TEMPLATE_IOCTQSET    _IO(TEMPLATE_IOC_MAGIC, 4)
#define TEMPLATE_IOCGQUANTUM   _IOR(TEMPLATE_IOC_MAGIC, 5, int)
#define TEMPLATE_IOCGQSET    _IOR(TEMPLATE_IOC_MAGIC, 6, int)
#define TEMPLATE_IOCQQUANTUM   _IO(TEMPLATE_IOC_MAGIC, 7)
#define TEMPLATE_IOCQQSET    _IO(TEMPLATE_IOC_MAGIC, 8)
#define TEMPLATE_IOCXQUANTUM   _IOWR(TEMPLATE_IOC_MAGIC, 9, int)
#define TEMPLATE_IOCXQSET    _IOWR(TEMPLATE_IOC_MAGIC, 10, int)
#define TEMPLATE_IOCHQUANTUM   _IO(TEMPLATE_IOC_MAGIC, 11)
#define TEMPLATE_IOCHQSET    _IO(TEMPLATE_IOC_MAGIC, 12)

#define TEMPLATE_P_IOCTSIZE   _IO(TEMPLATE_MAGIC,  13)
#define TEMPLATE_P_IOCQSIZE   _IO(TEMPLATE_MAGIC,  14)

#define TEMPLATE_IOC_MAXNR    14


#endif

 

 

main.c - module 의 메인

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>  // printk()
#include <linux/slab.h>   // kmalloc()
#include <linux/fs.h>   //
#include <linux/errno.h>  // error code
#include <linux/types.h>  // size_t
#include <linux/proc_fs.h>
#include <linux/fcntl.h>  // O_ACCMODE
#include <linux/cdev.h>

#include <asm/system.h>   // cli(), *_flags
#include <asm/uaccess.h>  // copy_*_user()

#include "template.h"

int template_major  = TEMPLATE_MAJOR;
int template_minor  = 0;
int template_nr_devs = 0;
char global_data[100];

module_param( template_major, int, S_IRUGO );
module_param( template_minor, int, S_IRUGO );

MODULE_AUTHOR( "Choi, Jae-woo" );
MODULE_LICENSE( "Dual BSD/GPL" );

int template_open( struct inode *inode, struct file *filp )
{
 return 0;
}

int template_release( struct inode *inode, struct file *filp )
{
 return 0;
}

ssize_t template_read( struct file *filp, char __user *buf, size_t count, loff_t *f_pos )
{
 ssize_t retval = 0;


 // down_interruptible();

 // .....

 if ( copy_from_user( global_data, buf, count ) )
 {
  retval = -EFAULT;
  goto out;
 }

 *f_pos += count;
 retval = count;

out:
 // up();

 return retval;
}

ssize_t template_write( struct file *filp, const char __user *buf, size_t count, loff_t *f_pos )
{
 ssize_t retval = 0;

 // down_interruptible();

 // .....

 if ( copy_from_user( global_data, buf, count ) )
 {
  retval = -EFAULT;
  goto out;
 }

 *f_pos += count;
 retval = count;

out:
 // up( );

 return retval;
}

int template_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg )
{
 int err = 0;
 int retval = 0;

 if ( _IOC_TYPE( cmd ) != TEMPLATE_IOC_MAGIC )
  return -ENOTTY;

 if ( _IOC_NR( cmd ) > TEMPLATE_IOC_MAXNR )
  return -ENOTTY;

 if ( _IOC_DIR( cmd ) & _IOC_READ )
  err = ! access_ok( VERIFY_WRITE, (void __user *) arg, _IOC_SIZE( cmd ) );

 else if ( _IOC_DIR( cmd ) & _IOC_WRITE )
  err = ! access_ok( VERIFY_READ, (void __user *) arg, _IOC_SIZE( cmd ) );

 if ( err )
  return -EFAULT;

 switch ( cmd )
 {
  case TEMPLATE_IOCRESET:
   break;

  default:
   return -ENOTTY;
   
 }

 return retval;
}

loff_t template_llseek( struct file *filp, loff_t off, int whence )
{
 loff_t newpos;

 switch ( whence )
 {
  case 0 :  // SEEK_SET
   newpos = off;
   break;

  case 1 :  // SEEK_CUR
   newpos = filp->f_pos + off;
   break;

  case 2 :  // SEEK_END
   newpos = sizeof( global_data ) + off;
   break;

  default :
   return -EINVAL;
 }

 if ( newpos < 0 )
  return -EINVAL;

 filp->f_pos = newpos;

 return newpos;
}


struct file_operations template_fops =
{
 .owner   = THIS_MODULE,
 .llseek   = template_llseek,
 .read   = template_read,
 .write   = template_write,
 .ioctl   = template_ioctl,
 .open   = template_open,
 .release  = template_release,
};

static void template_cleanup_module( void )
{
 dev_t devno = MKDEV( template_major, template_minor );


// template_remove_proc( );

 unregister_chrdev_region( devno, template_nr_devs );

}

static int template_init_module( void )
{
 int result;
 dev_t dev = 0;

 result = alloc_chrdev_region( &dev, template_minor, template_nr_devs, "template" );
 template_major = MAJOR( dev );

 if ( result < 0 )
 {
  printk( KERN_WARNING "template: can't get major %d\n", template_major );

  return result;
 }

 dev = MKDEV( template_major, template_minor + template_nr_devs );

// template_create_proc( );

 return 0;
}


module_init( template_init_module );
module_exit( template_cleanup_module );

proc.c - proc fs 관련

#include <linux/module.h>
#include <linux/kernel.h>  // printk()
#include <linux/slab.h>   // kmalloc()
#include <linux/fs.h>   //
#include <linux/errno.h>  // error code
#include <linux/types.h>  // size_t
#include <linux/proc_fs.h>
// #include <linux/fcntl.h>  // O_ACCMODE
#include <linux/seq_file.h>
#include <linux/cdev.h>

// #include <asm/system.h>   // cli(), *_flags
// #include <asm/uaccess.h>  // copy_*_user()

#include "template.h"


int template_read_procmem( char *buf, char **start, off_t offset, int count, int *eof, void *data )
{
 int len = 0;

 return len;
}

static void *template_seq_start( struct seq_file *s, loff_t *pos )
{
 return (void *) NULL;
}

static void *template_seq_next( struct seq_file *s, void *v, loff_t *pos )
{
 return (void *) NULL;
}

static void template_seq_stop( struct seq_file *s, void *v )
{
}

static int template_seq_show( struct seq_file *s, void *v )
{
 return 0;
}

static struct seq_operations template_seq_ops =
{
 .start = template_seq_start,
 .next = template_seq_next,
 .stop = template_seq_stop,
 .show = template_seq_show
};

static int template_proc_open( struct inode *inode, struct file *file )
{
 return seq_open( file, &template_seq_ops );
}

static struct file_operations template_proc_ops =
{
 .owner  = THIS_MODULE,
 .open  = template_proc_open,
 .read  = seq_read,
 .llseek  = seq_lseek,
 .release = seq_release
};

void template_create_proc( void )
{
 struct proc_dir_entry *entry;

 create_proc_read_entry( "templatemem", 0, NULL, template_read_procmem, NULL );
 entry = create_proc_entry( "templateseq", 0, NULL );

 if ( entry )
  entry->proc_fops = &template_proc_ops;
}

void template_remove_proc( void )
{
 remove_proc_entry( "templatemem", NULL );
 remove_proc_entry( "templateseq", NULL );
}

 

 

utils.c - 기타 함수들

#include <linux/kernel.h>  // printk()
#include <linux/slab.h>   // kmalloc()
#include <linux/cdev.h>

#include "template.h"

 

module_template.tar
0.02MB