linux驱动学习示例


driver.c

#include <linux/init.h>
#include <linux/kernel.h>
//  /usr/src/linux-headers-4.13.0-17
#include "linux/module.h"
#include <linux/types.h>
#include <linux/fs.h> //file_operations
#include <linux/cdev.h> //cdev
#include <linux/slab.h> //kmalloc kfree
#include <linux/uaccess.h> //copy_to_user copy_from_user
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter.h>
#include <linux/sched.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h> //init_net变量在其中


/******************************* Define Constant Macro ******************/
#ifndef DEVICE_NAME
#define DEVICE_NAME "KeyboardTouches"
#endif
#ifndef MINOR_COUNT
#define MINOR_COUNT 1
#endif
#ifndef RECV_SIZE
#define RECV_SIZE  512
#endif


/*******************************回调函数声明*********************************/
ssize_t fileRead(struct file *pFile,char __user *buffer,size_t count,loff_t *offset);
ssize_t fileWrite(struct file *pFile,const char __user *buffer,size_t count,loff_t *offset);


struct file_operations fop= {
.owner=THIS_MODULE,
.llseek=NULL,
.open=NULL,
//.ioctl=NULL,
.release=NULL,
.read=fileRead,
.write=fileWrite,
.release=NULL
};

/**************************变量定义*************************/
char *recvBuffer=NULL;
int result=0;
static struct nf_hook_ops nfhop;
struct cdev device;
dev_t deviceNo;
struct net_device *nd;

/************************** Function: filterSocket******************************/
unsigned int filterSocket(void *priv,struct sk_buff *skb,const struct nf_hook_state *state){

  printk(KERN_INFO "%s execute in driver:%s .\n",__FUNCTION__,DEVICE_NAME);
  //无条件丢包,阻断一切与外界的联系
  return NF_DROP;
}
int fileOpen(struct inode *node,struct file *pFile){
  return 0;
}

/******************************* Function: fileRead**************************/
ssize_t fileRead(struct file *pFile,char __user *buffer,size_t count,loff_t *offset){
  result=copy_to_user(buffer,recvBuffer,count);
  if (result<0) {
    //只有加了换行符之后才能立刻在控制台输出
    printk(KERN_INFO "Read buffer from device failed with error code:%d\n",result);
    return result;
  }
  return 0;
}

/******************************   Function: fileWrite ***********************/
ssize_t fileWrite(struct file *pFile,const char __user *buffer,size_t count,loff_t *offset){
  if (count>=RECV_SIZE) {
    printk_deferred(KERN_ALERT "Write to device data quantity (%d Bytes) is more than recieve buffer size (%d Bytes).\n",count,RECV_SIZE);
    return 0;
  }
  printk(KERN_ALERT "Write length:%ld\n",count);
  result=copy_from_user(recvBuffer,buffer,count);
  if (result<0) {
    printk(KERN_INFO "Write to device failed with error code:%d\n",result);
    return result;
  }
  return 0;
}

/******************************** Function: fileClose ***********************/
int fileClose(struct inode *node,struct file *pFile){
  return 0;
}


/****************************** Function: startDriver **********************/
static int __init startDriver(void){
  //初始化nfhop

  recvBuffer=kmalloc(RECV_SIZE,GFP_KERNEL);
  //申请设备号
  result=alloc_chrdev_region(&deviceNo,0,MINOR_COUNT,DEVICE_NAME);

  if (result<0) {
    printk(KERN_INFO "Allocate character device number failed!\n");
    return result;
  }
  printk(KERN_INFO "Allocate device suceeded! Master: %d, Slave:%d\n",MAJOR(deviceNo),MINOR(deviceNo));
  //对设备与文件操作进行绑定
  cdev_init(&device,&fop);
  //对设备与dev_t进行绑定
  result=cdev_add(&device,deviceNo,MINOR_COUNT);
  if (result<0) {
    //注册字符设备
    unregister_chrdev_region(deviceNo,MINOR_COUNT);
    printk(KERN_INFO "Add device to system failed! Unregister Master: %d, Slave:%d\n",MAJOR(deviceNo),MINOR(deviceNo));
    return result;
  }

  //注册网络钩子进行丢包操作

  //获得当前网卡设备,这里的名称可以通过ifconfig获得,此处为enp8s0
  nd=dev_get_by_name(current->nsproxy->net_ns, "enp8s0"); //current->nsproxy->net_ns用&init_net代替也是可以的
  printk(KERN_INFO "Get net device %s in kernel.\n",nd->name);
  //配置钩子
  nfhop.hook=filterSocket;
  nfhop.pf=PF_INET;
  nfhop.hooknum=NF_INET_PRE_ROUTING,
  nfhop.priority=NF_IP_PRI_FIRST;
  nfhop.dev=nd;

  //注册网络钩子
  nf_register_net_hook(current->nsproxy->net_ns,&nfhop);

  printk(KERN_INFO "the driver %s is started.\n",__FUNCTION__);
  return 0;
}

/******************************* Function: exitDriver **************************/
static void __exit exitDriver(void) {
  nf_unregister_net_hook(current->nsproxy->net_ns,&nfhop);
  //释放堆上的内存防止泄漏

  if (recvBuffer!=NULL) {
    kfree(recvBuffer);
  }
  //删除设备
  cdev_del(&device);
  //回收设备号
  unregister_chrdev_region(deviceNo,MINOR_COUNT);

  printk(KERN_INFO "the driver %s  exited.\n",__FUNCTION__);
}

/**************************** 例行公事 *******************************************/
module_init(startDriver);
module_exit(exitDriver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MOU MOU MOU");

Makefile

ifneq ($(KERNELRELEASE),)
	obj-m +=driver.o
else

	KDIR = /lib/modules/$(shell uname -r)/build
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif
clean:
	rm -rf *.o *.ko *.mod
	rm -rf .temp.versions
	rm *.order
	rm -f .driver.o.cmd
	rm -f .driver.ko.cmd
	rm -f .driver.mod.o.cmd
	rm -f driver.mod.c



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值