QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 5635|回复: 2

linux驱动中ioctl()的实现问题

[复制链接]
发表于 2013-1-16 09:24:46 | 显示全部楼层 |阅读模式
linux驱动中ioctl()的实现问题

ram_ioctl.h文件

  1. #define __RAM_IOCTL_H

  2. #define RAM_IOCOMMAND_CLEAR        0x1a
  3. #define RAM_IOCOMMAND_SET        0x1b
  4. #define RAM_IOCOMMAND_MOVE        0x1c

  5. #define        RAM_IOCTL_MAGIC 'k'

  6. #define        RAM_IOCTL_NR_MIN        RAM_IOCOMMAND_CLEAR
  7. #define RAM_IOCTL_NR_MAX        RAM_IOCOMMAND_MOVE

  8. #define RAM_IOCTL_CLEAR _IO( RAM_IOCTL_MAGIC, RAM_IOCOMMAND_CLEAR )
  9. #define RAM_IOCTL_SET        _IO( RAM_IOCTL_MAGIC, RAM_IOCOMMAND_SET )
  10. #define RAM_IOCTL_MOVE        _IO( RAM_IOCTL_MAGIC, RAM_IOCOMMAND_MOVE)


  11. #endif
复制代码
ram.c文件中的ioctl()

  1. static int ram_ioctl(struct block_device *bdev,fmode_t mode, unsigned int cmd, unsigned long arg)
  2. {

  3.         int ret = 0;        
  4.         if ( RAM_IOCTL_MAGIC != _IOC_TYPE( cmd ))
  5.         {
  6.                 printk(KERN_ALERT "RamDeviceDriver: ioctype mismatch !\n");
  7.                 return ret;
  8.         }

  9.         if ( ( RAM_IOCTL_NR_MIN > _IOC_NR( cmd ) ) || ( RAM_IOCTL_NR_MAX < _IOC_NR( cmd ) ) )
  10.         {
  11.                 printk(KERN_ALERT "RamDeviceDriver: iocnr mismatch !\n");
  12.                 return ret;
  13.         }

  14.         switch (cmd)
  15.         {
  16.                 case RAM_IOCTL_CLEAR:
  17.                         memset(ram_data_addr, 0, RAM_DATA_SIZE);
  18.                         printk(KERN_ALERT "RamDeviceDriver:Success to clear memory !\n");
  19.                         break;
  20.                 case RAM_IOCTL_SET:
  21.                         memset(ram_data_addr, arg, RAM_DATA_SIZE);
  22.                         printk(KERN_ALERT "RamDeviceDriver:Success to set memory !arg = %ld\n",arg);
  23.                         break;
  24.                 case RAM_IOCTL_MOVE:
  25.                         memcpy(ram_data_addr, ram_data_addr + MY_DATA_SIZE, MY_DATA_SIZE );
  26.                         printk(KERN_ALERT "RamDeviceDriver:Success to move data !\n");
  27.                         break;
  28.                 default:
  29.                         printk(KERN_ALERT "RamDeviceDriver:Unknown ioctl commd !\n");
  30.                         return -EINVAL;

  31.         }
  32. }

复制代码


test.c文件

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <sys/ioctl.h>
  6. #include "ram_ioctl.h"
  7. int main ( void )
  8. {
  9.         int fd;
  10.         int ret;
  11.         char buf[20];

  12.         fd = open( "/dev/myram", O_RDWR );

  13.         if ( fd < 0 )
  14.         {
  15.         perror( " open" );
  16.         return -1;
  17.         }

  18.         ret = write( fd, "wensheng",10 );
  19.         if ( ret < 0 )
  20.                 perror( "write" );
  21.         printf( "write %d byte\n", ret );
  22.         ioctl( fd, RAM_IOCTL_CLEAR );
  23.         close(fd);

  24.        fd = open( "/dev/myram", O_RDWR );
  25.         ret = read( fd, buf, 10 );

  26.         if ( ret < 0 )
  27.                 perror( "read" );

  28.         printf ( "buf is :%s\n",buf );
  29.         close(fd);
  30.         return 0;
  31. }

复制代码


问题如下:

   运行测试程序时,输出,write 10 byte
                                          buf is :wensheng
    查看dmesg信息 :RamDeviceDriver:Success to clear memory !

    可以看出,程序已经成功写入了“wensheng”字符串,并通过ioctl( fd, RAM_IOCTL_CLEAR );调用驱动中的ioctl() 执行 memset(ram_data_addr, 0, RAM_DATA_SIZE);(其中ram_data_addr是申请得到的内核虚拟内存的起始地址,RAM_DATA_SIZE内存大小)输出:RamDeviceDriver:Success to clear memory !信息。那么我块设备应该已经全部置0,为什么之后却又可以成功读出“wensheng”,其中求大神指点,那里出问题了,谢谢!!!
发表于 2013-1-16 23:35:32 | 显示全部楼层
嗯,你试着把
close(fd);
ioctl( fd, RAM_IOCTL_CLEAR );
这两句调换过来。
回复

使用道具 举报

 楼主| 发表于 2013-1-17 09:52:31 | 显示全部楼层
先谢谢您能回贴,问题我刚刚已解,原因:write(),read()为I/O操作,写入文件时,系统会先将要写入的数据写入缓冲区(这是为以提高读写速度),只有遇到close()时才将缓冲区数据写入实际文件(没查到很准确的资料,但大概是这个意思)。将程序中的ioctl操作单独执行,如下代码:
  1.   #include <stdio.h>
  2.   #include <sys/types.h>
  3.   #include <sys/stat.h>
  4.   #include <fcntl.h>
  5.   #include <sys/ioctl.h>
  6.    #include "ram_ioctl.h"
  7.    int main ( void )
  8.    {
  9.        int fd;
  10.       int ret;
  11.       char buf[20] = { 0 };
  12.       unsigned long int arg = 0xFF;
  13.       fd = open( "/dev/myram", O_RDWR );

  14.       if ( fd < 0 )
  15.       {
  16.       perror( " open" );
  17.       return -1;
  18.       }

  19.       ret = write( fd, "wensheng123 \n",  );
  20.      if ( ret < 0 )
  21.          perror( "write" );
  22.      printf( "write %d byte\n", ret );


  23. /*  if ( ioctl( fd, RAM_IOCTL_CLEAR ) < 0 )
  24.      {
  25.          perror( "ioctl error\n " );
  26.          return -1;
  27.      }

  28.      if ( ioctl( fd, RAM_IOCTL_SET , arg ) < 0 )
  29.      {
  30.          perror( "ioctl error123 \n" );
  31.          return -1;
  32.      }
  33. */
  34.      close( fd );

  35.      fd = open( "/dev/myram", O_RDWR );
  36.       ioctl( fd, RAM_IOCTL_SET, arg );
  37.       close( fd );

  38.       fd = open( "/dev/myram", O_RDWR );
  39.       ret = read( fd, buf, 20 );

  40.       if ( ret < 0 )
  41.           perror( "read" );
  42.       printf ( "buf is :%s\n", buf );
  43.       close( fd );
  44.       return 0;


复制代码
这样我ioctl操作就能按我想的那样工作,


呵呵-- 谢谢您和大家观注,在此结贴
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-1 22:33 , Processed in 0.042052 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表