linux2.6字符驱动(二)

现在看一下一个字符驱动的源代码,可以对字符设备整体构造有个大概的了解。
 

1   #include <linux/module.h>

2   #include <linux/types.h>

3   #include <linux/fs.h>

4   #include <linux/errno.h>

5   #include <linux/mm.h>

6   #include <linux/sched.h>

7   #include <linux/init.h>

8   #include <linux/cdev.h>

9   #include <asm/io.h>

10  #include <asm/system.h>

11  #include <asm/uaccess.h>

12 

13  #define GLOBALMEM_SIZE      0x1000    /*全局内存最大4K字节*/

14  #define MEM_CLEAR 0x1  /*0全局内存*/

15  #define GLOBALMEM_MAJOR 254    /*预设的globalmem的主设备号*/

16 

17  static globalmem_major = GLOBALMEM_MAJOR;

18  /*globalmem设备结构体*/

19  struct globalmem_dev                                    

20  {                                                        

21    struct cdev cdev; /*cdev结构体*/                      

22    unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/       

23  };

24 

25  struct globalmem_dev *globalmem_devp; /*设备结构体指针*/

26  /*文件打开函数*/

27  int globalmem_open(struct inode *inode, struct file *filp)

28  {

29    /*将设备结构体指针赋值给文件私有数据指针*/

30    filp->private_data = globalmem_devp;

31    return 0;

32  }

33  /*文件释放函数*/

34  int globalmem_release(struct inode *inode, struct file *filp)

35  {

36    return 0;

37  }

38 

39  /* ioctl设备控制函数 */

40  static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned

41    int cmd, unsigned long arg)

42  {

43    struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/

44 

45    switch (cmd)

46    {

47      case MEM_CLEAR:

48        memset(dev->mem, 0, GLOBALMEM_SIZE);     

49        printk(KERN_INFO "globalmem is set to zero/n");

50        break;

51 

52      default:

53        return  - EINVAL;

54    }

55    return 0;

56  }

57 

58  /*读函数*/

59  static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,

60    loff_t *ppos)

61  {

62    unsigned long p =  *ppos;

63    unsigned int count = size;

64    int ret = 0;

65    struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/

66 

67    /*分析和获取有效的写长度*/

68    if (p >= GLOBALMEM_SIZE)

69      return count ?  - ENXIO: 0;

70    if (count > GLOBALMEM_SIZE - p)

71      count = GLOBALMEM_SIZE - p;

72 

73    /*内核空间->用户空间*/

74    if (copy_to_user(buf, (void*)(dev->mem + p), count))

75    {

76      ret =  - EFAULT;

77    }

78    else

79    {

80      *ppos += count;

81      ret = count;

82     

83      printk(KERN_INFO "read %d bytes(s) from %d/n", count, p);

84    }

85 

86    return ret;

87  }

88 

89  /*写函数*/

90  static ssize_t globalmem_write(struct file *filp, const char __user *buf,

91    size_t size, loff_t *ppos)

92  {

93    unsigned long p =  *ppos;

94    unsigned int count = size;

95    int ret = 0;

96    struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/

97   

98    /*分析和获取有效的写长度*/

99    if (p >= GLOBALMEM_SIZE)

100     return count ?  - ENXIO: 0;

101   if (count > GLOBALMEM_SIZE - p)

102     count = GLOBALMEM_SIZE - p;

103    

104   /*用户空间->内核空间*/

105   if (copy_from_user(dev->mem + p, buf, count))

106     ret =  - EFAULT;

107   else

108   {

109     *ppos += count;

110     ret = count;

111    

112     printk(KERN_INFO "written %d bytes(s) from %d/n", count, p);

113   }

114

115   return ret;

116 }

117

118 /* seek文件定位函数 */

119 static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)

120 {

121   loff_t ret = 0;

122   switch (orig)

123   {

124     case 0:   /*相对文件开始位置偏移*/

125       if (offset < 0)

126       {

127         ret =  - EINVAL;

128         break;

129       }

130       if ((unsigned int)offset > GLOBALMEM_SIZE)

131       {

132         ret =  - EINVAL;

133         break;

134       }

135       filp->f_pos = (unsigned int)offset;

136       ret = filp->f_pos;

137       break;

138     case 1:   /*相对文件当前位置偏移*/

139       if ((filp->f_pos + offset) > GLOBALMEM_SIZE)

140       {

141         ret =  - EINVAL;

142         break;

143       }

144       if ((filp->f_pos + offset) < 0)

145       {

146         ret =  - EINVAL;

147         break;

148       }

149       filp->f_pos += offset;

150       ret = filp->f_pos;

151       break;

152     default:

153       ret =  - EINVAL;

154       break;

155   }

156   return ret;

157 }

158

159 /*文件操作结构体*/

160 static const struct file_operations globalmem_fops =

161 {

162   .owner = THIS_MODULE,

163   .llseek = globalmem_llseek,

164   .read = globalmem_read,

165   .write = globalmem_write,

166   .ioctl = globalmem_ioctl,

167   .open = globalmem_open,

168   .release = globalmem_release,

169 };

170

171 /*初始化并注册cdev*/

172 static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)

173 {

174   int err, devno = MKDEV(globalmem_major, index);

175

176   cdev_init(&dev->cdev, &globalmem_fops);

177   dev->cdev.owner = THIS_MODULE;

178   dev->cdev.ops = &globalmem_fops;

179   err = cdev_add(&dev->cdev, devno, 1);

180   if (err)

181     printk(KERN_NOTICE "Error %d adding LED%d", err, index);

182 }

183

184 /*设备驱动模块加载函数*/

185 int globalmem_init(void)

186 {

187   int result;

188   dev_t devno = MKDEV(globalmem_major, 0);

189

190   /* 申请设备号*/

191   if (globalmem_major)

192     result = register_chrdev_region(devno, 1, "globalmem");

193   else  /* 动态申请设备号 */

194   {

195     result = alloc_chrdev_region(&devno, 0, 1, "globalmem");

196     globalmem_major = MAJOR(devno);

197   } 

198   if (result < 0)

199     return result;

200    

201   /* 动态申请设备结构体的内存*/

202   globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);

203   if (!globalmem_devp)    /*申请失败*/

204   {

205     result =  - ENOMEM;

206     goto fail_malloc;

207   }

208   memset(globalmem_devp, 0, sizeof(struct globalmem_dev));

209  

210   globalmem_setup_cdev(globalmem_devp, 0);

211   return 0;

212

213   fail_malloc: unregister_chrdev_region(devno, 1);

214   return result;

215 }

216

217 /*模块卸载函数*/

218 void globalmem_exit(void)

219 {

220   cdev_del(&globalmem_devp->cdev);   /*注销cdev*/

221   kfree(globalmem_devp);     /*释放设备结构体内存*/

222   unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); /*释放设备号*/

223 }

224

225 MODULE_AUTHOR("Song Baohua");

226 MODULE_LICENSE("Dual BSD/GPL");

227

228 module_param(globalmem_major, int, S_IRUGO);

229

230 module_init(globalmem_init);

231 module_exit(globalmem_exit);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值