0
我想爲我的內核程序做一個讀取功能。首先用戶必須輸入一些數字(輸入數字0停止輸入)。數字輸入已經完成了我的工作是做閱讀功能。讀取功能必須跟蹤輸入的數量,並且它具有一個緩衝器,其中包含自模塊激活後輸入的數字。 我一直在從summer.c中讀取緩衝區和chars數到test-summer.c並打印它們。Linux內核讀取功能
Summer.c代碼:
/* example of a character device using ioctl
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include "summer.h"
#define BUF_LEN 80 /* Max length of the message from the device */
/* the memory of the device*/
int total;
/* Global variables declared as staic, so are global within the file.*/
static char *msg_Ptr;
static char msg[BUF_LEN];
/* called after the device is opened*/
int device_open(struct inode *inode, struct file *file)
{
printk("\nsummer device is open\n");
total = 0;
// sprintf(msg);
printk(msg);
msg_Ptr = msg;
return 0;
}
/* called after the device is closed
*/
int device_close(struct inode *inode, struct file *file)
{
printk("\nsummer device is closed\n");
return 0;
}
/* handling of ioctl events
*/
long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
int number;
switch(ioctl_num)
{
case SUMMER_SET:
__get_user(number, (int*)ioctl_param);
total += number;
break;
case SUMMER_GET:
__put_user(total, (int*)ioctl_param);
break;
}
return 0;
}
/* Read function */
static ssize_t device_read(struct file *filep, char *buffer, size_t length, loff_t *offset){
/* Number of bytes actually written to the buffer */
int bytes_read = 0;
/* If we're at the end of the message, return 0 signifying end of file */
if (*msg_Ptr == 0) return 0;
/* Actually put the data into the buffer */
while (length && *msg_Ptr) {
/* The buffer is in the user data segment, not the kernel segment;
* assignment won't work. We have to use put_use which copies data from
* the kernel data segment to the user data segment. */
put_user(*(msg_Ptr++), buffer++);
length--;
bytes_read++;
}
/* Most read functions return the number of bytes put into the buffer */
return bytes_read;
}
/* table of event handlers of the device
*/
struct file_operations fops =
{
read: device_read,
// write: device_write,
open: device_open,
release: device_close,
unlocked_ioctl: device_ioctl,
compat_ioctl: device_ioctl
};
/* called after the kernelmodule is opened
*/
int init_module(void)
{
/* register the device
** after registration the device is known to linux by its major number
** example: mknod /dev/summer0 c 240 0
** this creates the device /dev/summer0
** which is a character device (c) with major number 240 and minor number 0
*/
int retval = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fops);
if(retval < 0)
{
printk("character device not registered\n");
return retval;
}
printk("summer kernel module loaded\n");
return 0;
}
/* called after the module is closed
*/
void cleanup_module(void)
{
/* unregister the device
*/
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
printk("summer kernel module unloaded\n");
}
試驗summer.c代碼
/* example of use of a character device through ioctl
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "../summer.h"
int main(void)
{
int sum;
char* buffer;
/* open character device */
int fd = open("/dev/summer0", O_RDWR); // open device
if(fd < 0)
{
printf("no device found\n");
return;
}
/* read from device */
int nc = read(fd,buffer,4,0);
for(;;)
{
int num;
printf("Number (exit with 0) = ");
while(scanf("%d", &num) != 1)
;
printf("-- %d --\n", num);
if(num <= 0) break;
/* use ioctl to pass a value to the character device */
ioctl(fd, SUMMER_SET, &num);
}
/* use ioctl to get a value from the character device */
ioctl(fd, SUMMER_GET, &sum);
printf("Result = %d\n", sum);
/* print num of chars + the buffer as a string with the amount of numbers read since the kernel is active. */
printf("#char = %d\n", nc);
printf("Buffer: %s\n" , buffer);
close(fd); // close device
return 0;
}
有沒有理由不使用simple_read()? –
我使用這個閱讀的原因是,我在互聯網上找到了這個功能的例子 – Sybren