hello_world-3.1之增加操作函数fops(二)源码解析

               hello_world-3.1之增加操作函数fops(二)源码解析


1.helloworldmem.c



#include<linux/module.h>
#include<linux/init.h>
#include<linux/cdev.h>
#include<linux/fs.h>
#include<linux/errno.h> //-EFAULT
#include<linux/uaccess.h> //copy_to_user and copy_from_user
#include "helloworld_ioctl.h"


#define HELLOWORLDMEM_SIZE 0x1000
#define HELLOWORLDMEM_MAJOR 250

static int helloworldmem_major = HELLOWORLDMEM_MAJOR;

struct helloworldmem_dev {
   struct cdev cdev;
   unsigned char mem[HELLOWORLDMEM_SIZE];
};

struct helloworldmem_dev dev;
int helloworldmem_open(struct inode *inode,struct file *filp)
{
   return 0;

}
int helloworldmem_release(struct inode *inode,struct file *flip)
{
   return 0;

}
static ssize_t helloworldmem_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos)
{
  unsigned long p = *ppos;
  int ret = 0;
  if(p >= HELLOWORLDMEM_SIZE)
     return 0;
  if(count > HELLOWORLDMEM_SIZE - p)
     count = HELLOWORLDMEM_SIZE - p;
  if(copy_to_user(buf,(void*)(dev.mem + p),count))
     ret = -EFAULT;
  else{
   *ppos += count;
   ret = count;
   printk(KERN_INFO "read %d bytes(s) from %d \n",count,p);
  }
  return ret;
}

static ssize_t helloworldmem_write(struct file *filp,const char __user *buf,size_t count,loff_t *ppos)
{
   unsigned long p = *ppos;
   int ret = 0;
   if(p >= HELLOWORLDMEM_SIZE)
      return 0;
   if(count > HELLOWORLDMEM_SIZE - p)
      count = HELLOWORLDMEM_SIZE - p ;
   if(copy_from_user(dev.mem+p,buf,count))
      ret = -EFAULT;
   else{
      *ppos += count;
      ret = count;
      printk(KERN_INFO "written %d bytes from %d \n",count,p);
   }
   return ret;
}

static int helloworldmem_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
   switch(cmd){
      case HELLOWORLD_IOCTL_SAY_BYE:
         
         printk(KERN_INFO "HELLOWORLDMEM SAY BYE BYE to the world\n");
         break;
      /*case HELLOWORLD_IOCTL_SAY_HELLO:
         printk(KERN_INFO "HELLOWORLDMEM SAY HELLO to the world\n");
         
         break;*/
      default:
         return -EINVAL;
   }
   return 0;

}

static const struct file_operations helloworldmem_fops = {
   .owner = THIS_MODULE,
   .read = helloworldmem_read,
   .write = helloworldmem_write,
   .unlocked_ioctl = helloworldmem_ioctl,
   .open = helloworldmem_open,
   .release = helloworldmem_release,
};

static void helloworldmem_setup_cdev()
{
   int err,devno = MKDEV(helloworldmem_major,0);
   cdev_init(&dev.cdev,&helloworldmem_fops);
   dev.cdev.owner = THIS_MODULE;
   err = cdev_add(&dev.cdev,devno,1);
   if(err)
      printk(KERN_NOTICE "Error %d adding helloworldmem",err);
}

int __init helloworldmem_init(void)
{
   int result;
   dev_t devno = MKDEV(helloworldmem_major,0);
   if(helloworldmem_major)
      result = register_chrdev_region(devno,1,"helloworldmem");
   else
   {
      result = alloc_chrdev_region(&devno,0,1,"helloworldmem");
      helloworldmem_major = MAJOR(devno);
      
   
   }
   if(result < 0)
      return result;
   helloworldmem_setup_cdev();
   return 0;


}

void __exit helloworldmem_exit(void)
{
   cdev_del(&dev.cdev);
   unregister_chrdev_region(MKDEV(helloworldmem_major,0),1);
}
module_init(helloworldmem_init);
module_exit(helloworldmem_exit);
MODULE_LICENSE("GPL");

2. helloworld_ioctl.h


#ifndef __HELLOWORLD_IOCTL_H_
#define __HELLOWORLD_IOCTL_H
#include<linux/ioctl.h>

#define HELLOWORLD_MAGIC 12

#define HELLOWORLD_IOCTL_SAY_BYE _IO(HELLOWORLD_MAGIC,0)
//#define HELLOWORLD_IOCTL_SAY_HELLO _IO(HELLOWORLD_IOCTL_SAY_HELLO,1)

#endif

这里我有话要说,我当时准备是用两个IOCTL无读写方向的如上面那个“HELLOWORLD_IOCTL_SAY_HELLO”,但是这个宏在编译的时候老是提示未定义,我想应该是
这种_IO()函数只能用一次吧

还有那个HELLOWORLD_MAGIC 为幻数,是8位的,也可以用单个字符去定义。我上面的这个是定义无读写方向的IOCTL命令码。

/* used to create numbers */
#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))


其中size,表示命令码的位数,一把为int;

3.用户空间的程序hello.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<linux/errno.h>
#include "helloworld_ioctl.h"

int main(void)
{
   int fd = 0;
   int cmd;
   fd = open("/dev/helloworldmem",O_RDWR);
   if(fd < 0)
   {
      printf(" open helloworldmem failed\n");
      return -EFAULT;


   }
   cmd = HELLOWORLD_IOCTL_SAY_BYE;
   if(ioctl(fd,cmd) < 0)
   {
      printf("Called ioctl failed!\n");
   }

   close(fd);

}

4.执行结果及分析

4.1 对ioctl的结果分析

1.创建设备节点
mknod /dev/helloworldmem c 250 0

2.执行./hello后

从dmesg 可以看出:

[ 3891.531814] HELLOWORLDMEM SAY BYE BYE to the world

4.2 对read and write的结果分析
其实这个比较简单,直接应用shell的命令

写命令

root@thiz-H61H-G11:~# echo "helloworld" > /dev/helloworldmem

读命令

root@thiz-H61H-G11:~# cat /dev/helloworldmem 
helloworld












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值