热门搜索:Photoshop 平面设计 Linux Vista Windows ASP.NET qq word 病毒 XP Excel 标志设计 

Linux操作系统内核和设备文件对话

来源:天极(读取中...) 2006-11-17 【字体: 】 切换为

/* This function is called whenever a process tries to  
* do an ioctl on our device file. We get two extra  
* parameters (additional to the inode and file  
* structures, which all device functions get): the number  
* of the ioctl called and the parameter given to the  
* ioctl function.  
*  
* If the ioctl is write or read/write (meaning output  
* is returned to the calling process), the ioctl call  
* returns the output of this function.  
*/  
int device_ioctl(  
struct inode *inode,  
struct file *file,  
unsigned int ioctl_num,/* The number of the ioctl */  
unsigned long ioctl_param) /* The parameter to it */  
{  
int i;  
char *temp;  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  
char ch;  
#endif  

/* Switch according to the ioctl called */  
switch (ioctl_num) {  
case IOCTL_SET_MSG:  
/* Receive a pointer to a message (in user space)  
* and set that to be the devices message. */  

/* Get the parameter given to ioctl by the process */  
temp = (char *) ioctl_param;  

/* Find the length of the message */  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  
get_user(ch, temp);  
for (i=0; ch && ibr temp++) i++,> get_user(ch, temp);  
#else  
for (i=0; get_user(temp) && ibr temp++) i++,> ;  
#endif  

/* Dont reinvent the wheel - call device_write */  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  
device_write(file, (char *) ioctl_param, i, 0);  
#else  
device_write(inode, file, (char *) ioctl_param, i);  
#endif  
break;  

case IOCTL_GET_MSG:  
/* Give the current message to the calling  
* process - the parameter we got is a pointer,  
* fill it. */  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  
i = device_read(file, (char *) ioctl_param, 99, 0);  
#else  
i = device_read(inode, file, (char *) ioctl_param,  
99);  
#endif  
/* Warning - we assume here the buffer length is  
* 100. If its less than that we might overflow  
* the buffer, causing the process to core dump.  
*  
* The reason we only allow up to 99 characters is  
* that the NULL which terminates the string also  
* needs room. */  

/* Put a zero at the end of the buffer, so it  
* will be properly terminated */  
put_user(\, (char *) ioctl_param+i);  
break;  

case IOCTL_GET_NTH_BYTE:  
/* This ioctl is both input (ioctl_param) and  
* output (the return value of this function) */  
return Message[ioctl_param];  
break;  
}  

return SUCCESS;  
}

  

/* Module Declarations *************************** */  
/* This structure will hold the functions to be called  
* when a process does something to the device we  
* created. Since a pointer to this structure is kept in  
* the devices table, it cant be local to  
* init_module. NULL is for unimplemented functions. */  
struct file_operations Fops = {  
NULL, /* seek */  
device_read,  
device_write,  
NULL, /* readdir */  
NULL, /* select */  
device_ioctl, /* ioctl */  
NULL, /* mmap */  
device_open,  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  
NULL, /* flush */  
#endif  
device_release /* a.k.a. close */  
};  


/* Initialize the module - Register the character device */  
int init_module()  
{  
int ret_val;  

/* Register the character device (atleast try) */  
ret_val = module_register_chrdev(MAJOR_NUM,  
DEVICE_NAME,  
&Fops);  

/* Negative values signify an error */  
if (ret_val < 0) {  
printk ("%s failed with %d\n",  
"Sorry, registering the character device ",  
ret_val);  
return ret_val;  
}  

printk ("%s The major device number is %d.\n",  
"Registeration is a success",  
MAJOR_NUM);  
printk ("If you want to talk to the device driver,\n");  
printk ("youll have to create a device file. \n");  
printk ("We suggest you use:\n");  
printk ("mknod %s c %d 0\n", DEVICE_FILE_NAME,  
MAJOR_NUM);  
printk ("The device file name is important, because\n");  
printk ("the ioctl program assumes thats the\n");  
printk ("file youll use.\n");  

return 0;  
}  


/* Cleanup - unregister the appropriate file from /proc */  
void cleanup_module()  
{  
int ret;  

/* Unregister the device */  
ret = module_unregister_chrdev(MAJOR_NUM, DEVICE_NAME);  

/* If theres an error, report it */  
if (ret < 0)  
printk("Error in module_unregister_chrdev: %d\n", ret);  
}  
ex chardev.h  

/* chardev.h - the header file with the ioctl definitions.  
*  
* The declarations here have to be in a header file,  
* because they need to be known both to the kernel  
* module (in chardev.c) and the process calling ioctl  
* (ioctl.c)  
*/  

#ifndef CHARDEV_H  
#define CHARDEV_H  

#include  



/* The major device number. We cant rely on dynamic  
* registration any more, because ioctls need to know  
* it. */  
#define MAJOR_NUM 100  


/* Set the message of the device driver */  
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)  
/* _IOR means that were creating an ioctl command  
* number for passing information from a user process  
* to the kernel module.  
*  
* The first arguments, MAJOR_NUM, is the major device  
* number were using.  
*  
* The second argument is the number of the command  
* (there could be several with different meanings).  
*  
* The third argument is the type we want to get from  
* the process to the kernel.  
*/  

/* Get the message of the device driver */  
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)  
/* This IOCTL is used for output, to get the message  
* of the device driver. However, we still need the  
* buffer to place the message in to be input,  
* as it is allocated by the process.  
*/  


/* Get the nth byte of the message */  
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)  
/* The IOCTL is used for both input and output. It  
* receives from the user a number, n, and returns  
* Message[n]. */  


/* The name of the device file */  
#define DEVICE_FILE_NAME "char_dev"  


#endif  

ex ioctl.c  

/* ioctl.c - the process to use ioctls to control the  
* kernel module  
*  
* Until now we could have used cat for input and  
* output. But now we need to do ioctls, which require  
* writing our own process.  
*/  

/* Copyright (C) 1998 by Ori Pomerantz */  


/* device specifics, such as ioctl numbers and the  
* major device file. */  
#include "chardev.h"  


#include /* open */  
#include /* exit */  
#include /* ioctl */  



/* Functions for the ioctl calls */  

ioctl_set_msg(int file_desc, char *message)  
{  
int ret_val;  

ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);  

if (ret_val < 0) {  
printf ("ioctl_set_msg failed:%d\n", ret_val);  
exit(-1);  
}  
}  



ioctl_get_msg(int file_desc)  
{  
int ret_val;  
char message[100];  

/* Warning - this is dangerous because we dont tell  
* the kernel how far its allowed to write, so it  
* might overflow the buffer. In a real production  
* program, we would have used two ioctls - one to tell  
* the kernel the buffer length and another to give  
* it the buffer to fill  
*/  
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);  

if (ret_val < 0) {  
printf ("ioctl_get_msg failed:%d\n", ret_val);  
exit(-1);  
}  

printf("get_msg message:%s\n", message);  
}  



ioctl_get_nth_byte(int file_desc)  
{  
int i;  
char c;  

printf("get_nth_byte message:");  

i = 0;  
while (c != 0) {  
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);  

if (c < 0) {  
printf(  
"ioctl_get_nth_byte failed at the %dth byte:\n", i);  
exit(-1);  
}  

putchar(c);  
}  
putchar(\n);  
}  




/* Main - Call the ioctl functions */  
main()  
{  
int file_desc, ret_val;  
char *msg = "Message passed by ioctl\n";  

file_desc = open(DEVICE_FILE_NAME, 0);  
if (file_desc < 0) {  
printf ("Cant open device file: %s\n",  
DEVICE_FILE_NAME);  
exit(-1);  
}  

ioctl_get_nth_byte(file_desc);  
ioctl_get_msg(file_desc);  
ioctl_set_msg(file_desc, msg);  

close(file_desc);  
}

上一页  [1] [2] [3] 

关注此文的读者还看过:
    用户评论
评论内容:不能超过100字,需审核,请自觉遵守互联网相关政策法规。
发表评论: 匿名发表 用户名: loading 位网友发表了评论 查看评论
(0/100)