编写Linux内存驱动程序以将小写转换为大写

时间:2014-07-23 23:35:19

标签: c linux memory driver

我正在做一个分配来构建一个内存驱动程序,它可以在Linux中将小写转换为大写。 Linux将通过echo和cat获取最后一个字节。它已经到期了。我尝试了几种方法,但都没有成功。

我做了char upper ='A'+(upper - 'a')或ASCII - 32 if(ASCII在a和z之间)。我试图将语句写入内存写入或读取。都没有工作。

这是memory.c。任何人都可以让我知道我承诺的错误是什么?我只是根据教师的示例代码进行更改。

/* Necessary includes for device drivers */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */


MODULE_LICENSE("Dual BSD/GPL");

/* Declaration of memory.c functions */
int memory_open(struct inode *inode, struct file *filp);
int memory_release(struct inode *inode, struct file *filp);
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t memory_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);
void memory_exit(void);
int memory_init(void);

/* Structure that declares the usual file */
/* access functions */
struct file_operations memory_fops =
{
  read: memory_read,
  write: memory_write,
  open: memory_open,
  release: memory_release
};

/* Declaration of the init and exit functions */
module_init(memory_init);
module_exit(memory_exit);

/* Global variables of the driver */
/* Major number */
int memory_major = 60;

/* Buffer to store data */
char *memory_buffer;



/* Memory Init Module */
int memory_init(void)
{
  int result;
  printk(KERN_ALERT "memory_init\n");

  /* Registering device */
  result = register_chrdev(memory_major, "memory", &memory_fops);
  if (result < 0) {
    printk(
      "<1>memory: cannot obtain major number %d\n", memory_major);
    return result;
  }

  /* Allocating memory for the buffer */
  memory_buffer = kmalloc(1, GFP_KERNEL);

  if(!memory_buffer)
  {
    memory_exit();
    return(-ENOMEM);
  }
  else
  {
    memset(memory_buffer, 0, 1);
    printk("<1>Inserting memory module\n");
    return 0;
  }
}



/* Memory Exit */
void memory_exit(void)
{

  printk("<1>Removing memory module\n");

  /* Freeing the major number */
  unregister_chrdev(memory_major, "memory");

  /* Freeing buffer memory */
  if (memory_buffer) {
    kfree(memory_buffer);
  }
}

/* Memory Open */
int memory_open(struct inode *inode, struct file *filp)
{
  printk(KERN_ALERT "memory_open\n");

  /* Success */
  return 0;
}

/* Memory Release */
int memory_release(struct inode *inode, struct file *filp)
{
  printk(KERN_ALERT "memory_release\n");

  /* Success */
  return 0;
}

/* Memory Read */
ssize_t memory_read(struct file *filp, char *buf,
                    size_t count, loff_t *f_pos)
{

  printk(KERN_ALERT "memory_read\n");
  /* Transfering data to user space */
  copy_to_user(buf,memory_buffer,1);  

  /* Changing reading position as best suits */
  if (*f_pos == 0)
  {
    *f_pos+=1;
    return 1;
  }
  else
  {
    return 0;
  }
}

/* Memory Write */
ssize_t memory_write( struct file *filp, char *buf,
                      size_t count, loff_t *f_pos)
{
  char *tmp;


  tmp=buf+count-1;
  copy_from_user(memory_buffer,tmp,1);
  char upper = 'A' + (upper - 'a'); // convert lower to upper case
  printk(KERN_ALERT "memory_write\n");

  return 1;
}

2 个答案:

答案 0 :(得分:3)

一些评论:

在memory_write的代码中,实际上是在“计算”char的大写字母之前将新内容写入内存。我说“计算”是因为你试图计算某些东西的大写,但是既没有定义也没有使用,所以编译器可能放弃了这一行,我正在谈论这一行:

char upper = 'A' + (upper - 'a'); // convert lower to upper case

如果我正确理解,你使用upper的当前值来定义upper的值,这是未定义的。

通过查看代码,您似乎应该在调用copy_from_user之前尝试修改* tmp的值(将其转换为大写)。

最后但并非最不重要的是,你没有考虑到计数,你假设用户只想在块的末尾复制1个字符,我不确定这是你想要做的或者不

简言之:

  • 您没有更改用户写入的值,这就是为什么它没有做任何事情
  • 您只是在用户提供的块末尾复制1个字符
  • 您尝试将字符更改为大写的代码是错误的

要解决大写部分,并考虑到您只打算复制1个字符而不是整个块,您可以尝试这样的事情:

/* Memory Write */
ssize_t memory_write( struct file *filp, char *buf,
                      size_t count, loff_t *f_pos)
{
  char *tmp;


  tmp=buf+count-1;
  copy_from_user(memory_buffer,tmp,1);//write to memory

  char to_upper=memory_buffer[0]; //grab the char
  if (to_upper >= 97 && to_upper <= 122) // if the char in is the range a-z
  {
     to_upper = to_upper - 32;// convert to uppercase
     memory_buffer[0] = to_upper;
  }
  printk(KERN_ALERT "memory_write\n");

  return 1;
}

希望它有所帮助!

答案 1 :(得分:0)

在memory_write中......

copy_from_user(memory_buffer,tmp,1);
*memory_buffer = 'A' + (*memory_buffer - 'a');