简体   繁体   中英

Linux kernel read function

I am trying to make a read function for my kernel program. First the user has to input some numbers (Input number 0 stops the input). The number input was already done for me my job was to make the read function. The read function has to keep track of the amount of inputted numbers and it has a buffer with the numbers inputted since the module is active. I'm stuck on getting the buffer and the number of chars from the read in summer.c to test-summer.c and print them.

Summer.c code:

   /* 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");
}

Test-summer.c code

/* 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;
}

It is an old question, but didn't want to leave it unanswered.

In test-summers.c file, you did not allocate memory for your buffer and pass it to the read function. That might be the reason why you are not getting the return value correct and also the buffer not getting filled with the data you wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM