📄 9.html
字号:
case IOCTL_SET_MSG:
/* Receive a pointer to a message (in user space)
* and set that to be the device\'s 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 && i<BUF_LEN; i++, temp++)
get_user(ch, temp);
#else
for (i=0; get_user(temp) && i<BUF_LEN; i++, temp++)
;
#endif
/* Don\'t 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 it\'s 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(\'\\0\', (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 can\'t 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 (\"you\'ll 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 that\'s the\\n\");
printk (\"file you\'ll 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 there\'s 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 <linux/ioctl.h>
/* The major device number. We can\'t 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 we\'re 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 we\'re 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 n\'th 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 ioctl\'s to control the
* kernel module
*
* Until now we could have used cat for input and
* output. But now we need to do ioctl\'s, 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 <fcntl.h> /* open */
#include <unistd.h> /* exit */
#include <sys/ioctl.h> /* 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 don\'t tell
* the kernel how far it\'s 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 %d\'th 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 (\"Can\'t 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);
}
</pre><hr><br><center><a href='8.html'>上一页 </a>||<a href='10.html'>下一页</a></center></div> </td> </tr> </table> <p> </p> </div> </td> </tr> </table> <br> <table border="0" width="75%"><tr><td align="right"><a href="/"><img src="/image2/logo_bottom.gif" border="0"></a></td></tr></table> <hr size="1" align="center" color="#eecccc"> <br> </div> </div> </td> </tr></table> <center><a href="http://ad.myrice.com/RealMedia/ads/click_nx.ads/goldnets.myrice.com/banner1@Bottom" target=_blanck ><script language=JavaScript><!---todayd = new Date();var seconds = todayd.getTime();document.write("<img src=\"http://ad.myrice.com/RealMedia/ads/adstream_nx.ads/goldnets.myrice.com/banner1@Bottom?dd=seconds\" border=0 width=468 height=60>");//--></script></a></center></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -