linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】

简介: 转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等。 用户空间函数原型:int ioctl(int fd,unsinged long cmd,...)   fd-文件描述符 cmd-对设备的发出的控制命令 ...表示这是一个可选的参数,存在与否依赖于cmd,如cmd为修改波特率,那么....就表示波特率的值。

转自:http://my.oschina.net/u/274829/blog/285014

1,ioctl介绍

ioctl控制设备读写数据以及关闭等。

用户空间函数原型:int ioctl(int fd,unsinged long cmd,...)

 

  • fd-文件描述符

  • cmd-对设备的发出的控制命令

  • ...表示这是一个可选的参数,存在与否依赖于cmd,如cmd为修改波特率,那么....就表示波特率的值。如果cmd表示关闭,则不需要参数

     

     

     

     

内核函数原型

file_operations结构体里面long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

 

ioctl命令段分为:类型,序号,传递方向,参数大小

  • Type 类型:表明哪个设备的命令,在参考了ioctl-number.txt之后选出,8位宽

  • Number 序号:表明设备命令中的第几个,8位宽

  • Direction 传送方向:可能的值是

    _IOC_NONE(没数据传输)

    _IOC_READ(从设备读)

    _IOC_WRITE

  • Size 用户参数大小:(13/14位宽,视处理器而定)

内核提供了一些宏来帮助定义命令:

  • _IO(type, nr )    type为命令类型  如int, nr为序号

    没有参数的命令

  • _IOR(type, nr, datatype)  

        从驱动中读数据,datatype 读的数据参数的类型

  • _IOW(type, nr, datatype)

        写数据到驱动

  • _IOWR(type,nr, datatype)

        读写数据

定义命令例子  #define MEM_IOC_MAGIC 'm'   //定义幻数,因为命令类型type是8位的所以找个字符代替

#define MEM_IOCSET

_IOW(MEM_IOC_MAGIC,0,int)   //命令 去写 一个 int型的数据

#define MEM_IOCGQSET

_IOR(MEM_IOC_MAGIC, 1, int)

 

2,ioctl命令使用时注意事项

用户使用int ioctl(int fd,unsinged long cmd,...)时,...就是要传递的参数

再通过long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long arg);中的arg传递,如果arg是一个整形,可以直接使用,如果是指针,我们必须确保这个用户地址是有效的,因此,使用之前需要进行正解的检查。

内部有检查的,不需要检测的:

Copy_from_user

Copy_to_user

Get_user

Put_user

需要检测的:

__get_user

__put_user

使用int access_ok(int type, const void *addr, unsigned long size)检测

Type 是VERIFY_READ 或者VERIFY_WRITE用来表明是读用户内存还是写用户内存。

Addr参数是要操作的用户内存地址,size是操作的长度。如果ioctl需要从用户空间读一个整数,那么size参数就等于sizeof(int)

内核读,写入用户空间,所以用户空间使用VERIFY_WRITE写验证用户内存是否可用。

Access_ok返回一个布尔值:1,是成功(存取没问题),失败,ioctr返回-EFAULT 

 

3,ioctl实现例程

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
 
#include "memdev.h"
 
static  int  mem_major = MEMDEV_MAJOR;
 
module_param(mem_major,  int , S_IRUGO);
 
struct  mem_dev *mem_devp;  /*设备结构体指针*/
 
struct  cdev cdev; 
 
/*文件打开函数*/
int  mem_open( struct  inode *inode,  struct  file *filp)
{
     struct  mem_dev *dev;
     
     /*获取次设备号*/
     int  num = MINOR(inode->i_rdev);
 
     if  (num >= MEMDEV_NR_DEVS) 
             return  -ENODEV;
     dev = &mem_devp[num];
     
     /*将设备描述结构指针赋值给文件私有数据指针*/
     filp->private_data = dev;
     
     return  0; 
}
 
/*文件释放函数*/
int  mem_release( struct  inode *inode,  struct  file *filp)
{
   return  0;
}
 
/*IO操作*/
int  memdev_ioctl( struct  inode *inode,  struct  file *filp, unsigned  int  cmd, unsigned  long  arg)
{
 
     int  err = 0;
     int  ret = 0;
     int  ioarg = 0;
     
     /* 检测命令的有效性 */
     if  (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC) 
         return  -EINVAL;
     if  (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR) 
         return  -EINVAL;
 
     /* 根据命令类型,检测参数空间是否可以访问 */
     if  (_IOC_DIR(cmd) & _IOC_READ)
         err = !access_ok(VERIFY_WRITE, ( void  *)arg, _IOC_SIZE(cmd));
     else  if  (_IOC_DIR(cmd) & _IOC_WRITE)
         err = !access_ok(VERIFY_READ, ( void  *)arg, _IOC_SIZE(cmd));
     if  (err) 
         return  -EFAULT;
 
     /* 根据命令,执行相应的操作 */
     switch (cmd) {
 
       /* 打印当前设备信息 */
       case  MEMDEV_IOCPRINT:
           printk( "<--- CMD MEMDEV_IOCPRINT Done--->\n\n" );
         break ;
       
       /* 获取参数 */
       case  MEMDEV_IOCGETDATA: 
         ioarg = 1101;
         ret = __put_user(ioarg, ( int  *)arg);
         break ;
       
       /* 设置参数 */
       case  MEMDEV_IOCSETDATA: 
         ret = __get_user(ioarg, ( int  *)arg);
         printk( "<--- In Kernel MEMDEV_IOCSETDATA ioarg = %d --->\n\n" ,ioarg);
         break ;
 
       default :  
         return  -EINVAL;
     }
     return  ret;
 
}
 
/*文件操作结构体*/
static  const  struct  file_operations mem_fops =
{
   .owner = THIS_MODULE,
   .open = mem_open,
   .release = mem_release,
   .ioctl = memdev_ioctl,
};
 
/*设备驱动模块加载函数*/
static  int  memdev_init( void )
{
   int  result;
   int  i;
 
   dev_t devno = MKDEV(mem_major, 0);
 
   /* 静态申请设备号*/
   if  (mem_major)
     result = register_chrdev_region(devno, 2,  "memdev" );
   else   /* 动态分配设备号 */
   {
     result = alloc_chrdev_region(&devno, 0, 2,  "memdev" );
     mem_major = MAJOR(devno);
   }  
   
   if  (result < 0)
     return  result;
 
   /*初始化cdev结构*/
   cdev_init(&cdev, &mem_fops);
   cdev.owner = THIS_MODULE;
   cdev.ops = &mem_fops;
   
   /* 注册字符设备 */
   cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
    
   /* 为设备描述结构分配内存*/
   mem_devp = kmalloc(MEMDEV_NR_DEVS *  sizeof ( struct  mem_dev), GFP_KERNEL);
   if  (!mem_devp)     /*申请失败*/
   {
     result =  - ENOMEM;
     goto  fail_malloc;
   }
   memset (mem_devp, 0,  sizeof ( struct  mem_dev));
   
   /*为设备分配内存*/
   for  (i=0; i < MEMDEV_NR_DEVS; i++) 
   {
         mem_devp[i].size = MEMDEV_SIZE;
         mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
         memset (mem_devp[i].data, 0, MEMDEV_SIZE);
   }
     
   return  0;
 
   fail_malloc: 
   unregister_chrdev_region(devno, 1);
   
   return  result;
}
 
/*模块卸载函数*/
static  void  memdev_exit( void )
{
   cdev_del(&cdev);    /*注销设备*/
   kfree(mem_devp);      /*释放设备结构体内存*/
   unregister_chrdev_region(MKDEV(mem_major, 0), 2);  /*释放设备号*/
}
 
MODULE_AUTHOR( "David Xie" );
MODULE_LICENSE( "GPL" );
 
module_init(memdev_init);
module_exit(memdev_exit);

 

.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef _MEMDEV_H_
#define _MEMDEV_H_
 
#include <linux/ioctl.h>
 
#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 190   /*预设的mem的主设备号*/
#endif
 
#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 2    /*设备数*/
#endif
 
#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 4096
#endif
 
/*mem设备描述结构体*/
struct  mem_dev                                     
{                                                        
   char  *data;                      
   unsigned  long  size;       
};
 
/* 定义幻数 */
#define MEMDEV_IOC_MAGIC  'k'
 
/* 定义命令 */
#define MEMDEV_IOCPRINT   _IO(MEMDEV_IOC_MAGIC, 1)
#define MEMDEV_IOCGETDATA _IOR(MEMDEV_IOC_MAGIC, 2, int)
#define MEMDEV_IOCSETDATA _IOW(MEMDEV_IOC_MAGIC, 3, int)
 
#define MEMDEV_IOC_MAXNR 3
 
#endif /* _MEMDEV_H_ */

 

Makefile

?
1
2
3
4
5
6
7
8
9
10
11
12
13
ifneq ($(KERNELRELEASE),)
 
obj-m := memdev.o
 
else
     
KDIR := /forlinux/linux-3.0.1
all:
     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*
 
endif

 

测试程序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
 
#include "memdev.h"  /* 包含命令定义 */
 
int  main()
{
     int  fd = 0;
     int  cmd;
     int  arg = 0;
     char  Buf[4096];
     
     
     /*打开设备文件*/
     fd = open( "/dev/memdev0" ,O_RDWR);
     if  (fd < 0)
     {
         printf ( "Open Dev Mem0 Error!\n" );
         return  -1;
     }
     
     /* 调用命令MEMDEV_IOCPRINT */
     printf ( "<--- Call MEMDEV_IOCPRINT --->\n" );
     cmd = MEMDEV_IOCPRINT;
     if  (ioctl(fd, cmd, &arg) < 0)
         {
             printf ( "Call cmd MEMDEV_IOCPRINT fail\n" );
             return  -1;
     }
     
     
     /* 调用命令MEMDEV_IOCSETDATA */
     printf ( "<--- Call MEMDEV_IOCSETDATA --->\n" );
     cmd = MEMDEV_IOCSETDATA;
     arg = 2007;
     if  (ioctl(fd, cmd, &arg) < 0)
         {
             printf ( "Call cmd MEMDEV_IOCSETDATA fail\n" );
             return  -1;
     }
 
     
     /* 调用命令MEMDEV_IOCGETDATA */
     printf ( "<--- Call MEMDEV_IOCGETDATA --->\n" );
     cmd = MEMDEV_IOCGETDATA;
     if  (ioctl(fd, cmd, &arg) < 0)
         {
             printf ( "Call cmd MEMDEV_IOCGETDATA fail\n" );
             return  -1;
     }
     printf ( "<--- In User Space MEMDEV_IOCGETDATA Get Data is %d --->\n\n" ,arg); 
     
     close(fd);
     return  0; 
}

1,ioctl介绍

ioctl控制设备读写数据以及关闭等。

用户空间函数原型:int ioctl(int fd,unsinged long cmd,...)

 

  • fd-文件描述符

  • cmd-对设备的发出的控制命令

  • ...表示这是一个可选的参数,存在与否依赖于cmd,如cmd为修改波特率,那么....就表示波特率的值。如果cmd表示关闭,则不需要参数

     

     

     

     

内核函数原型

file_operations结构体里面long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

 

ioctl命令段分为:类型,序号,传递方向,参数大小

  • Type 类型:表明哪个设备的命令,在参考了ioctl-number.txt之后选出,8位宽

  • Number 序号:表明设备命令中的第几个,8位宽

  • Direction 传送方向:可能的值是

    _IOC_NONE(没数据传输)

    _IOC_READ(从设备读)

    _IOC_WRITE

  • Size 用户参数大小:(13/14位宽,视处理器而定)

内核提供了一些宏来帮助定义命令:

  • _IO(type, nr )    type为命令类型  如int, nr为序号

    没有参数的命令

  • _IOR(type, nr, datatype)  

        从驱动中读数据,datatype 读的数据参数的类型

  • _IOW(type, nr, datatype)

        写数据到驱动

  • _IOWR(type,nr, datatype)

        读写数据

定义命令例子  #define MEM_IOC_MAGIC 'm'   //定义幻数,因为命令类型type是8位的所以找个字符代替

#define MEM_IOCSET

_IOW(MEM_IOC_MAGIC,0,int)   //命令 去写 一个 int型的数据

#define MEM_IOCGQSET

_IOR(MEM_IOC_MAGIC, 1, int)

 

2,ioctl命令使用时注意事项

用户使用int ioctl(int fd,unsinged long cmd,...)时,...就是要传递的参数

再通过long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long arg);中的arg传递,如果arg是一个整形,可以直接使用,如果是指针,我们必须确保这个用户地址是有效的,因此,使用之前需要进行正解的检查。

内部有检查的,不需要检测的:

Copy_from_user

Copy_to_user

Get_user

Put_user

需要检测的:

__get_user

__put_user

使用int access_ok(int type, const void *addr, unsigned long size)检测

Type 是VERIFY_READ 或者VERIFY_WRITE用来表明是读用户内存还是写用户内存。

Addr参数是要操作的用户内存地址,size是操作的长度。如果ioctl需要从用户空间读一个整数,那么size参数就等于sizeof(int)

内核读,写入用户空间,所以用户空间使用VERIFY_WRITE写验证用户内存是否可用。

Access_ok返回一个布尔值:1,是成功(存取没问题),失败,ioctr返回-EFAULT 

 

3,ioctl实现例程

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
 
#include "memdev.h"
 
static  int  mem_major = MEMDEV_MAJOR;
 
module_param(mem_major,  int , S_IRUGO);
 
struct  mem_dev *mem_devp;  /*设备结构体指针*/
 
struct  cdev cdev; 
 
/*文件打开函数*/
int  mem_open( struct  inode *inode,  struct  file *filp)
{
     struct  mem_dev *dev;
     
     /*获取次设备号*/
     int  num = MINOR(inode->i_rdev);
 
     if  (num >= MEMDEV_NR_DEVS) 
             return  -ENODEV;
     dev = &mem_devp[num];
     
     /*将设备描述结构指针赋值给文件私有数据指针*/
     filp->private_data = dev;
     
     return  0; 
}
 
/*文件释放函数*/
int  mem_release( struct  inode *inode,  struct  file *filp)
{
   return  0;
}
 
/*IO操作*/
int  memdev_ioctl( struct  inode *inode,  struct  file *filp, unsigned  int  cmd, unsigned  long  arg)
{
 
     int  err = 0;
     int  ret = 0;
     int  ioarg = 0;
     
     /* 检测命令的有效性 */
     if  (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC) 
         return  -EINVAL;
     if  (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR) 
         return  -EINVAL;
 
     /* 根据命令类型,检测参数空间是否可以访问 */
     if  (_IOC_DIR(cmd) & _IOC_READ)
         err = !access_ok(VERIFY_WRITE, ( void  *)arg, _IOC_SIZE(cmd));
     else  if  (_IOC_DIR(cmd) & _IOC_WRITE)
         err = !access_ok(VERIFY_READ, ( void  *)arg, _IOC_SIZE(cmd));
     if  (err) 
         return  -EFAULT;
 
     /* 根据命令,执行相应的操作 */
     switch (cmd) {
 
       /* 打印当前设备信息 */
       case  MEMDEV_IOCPRINT:
           printk( "<--- CMD MEMDEV_IOCPRINT Done--->\n\n" );
         break ;
       
       /* 获取参数 */
       case  MEMDEV_IOCGETDATA: 
         ioarg = 1101;
         ret = __put_user(ioarg, ( int  *)arg);
         break ;
       
       /* 设置参数 */
       case  MEMDEV_IOCSETDATA: 
         ret = __get_user(ioarg, ( int  *)arg);
         printk( "<--- In Kernel MEMDEV_IOCSETDATA ioarg = %d --->\n\n" ,ioarg);
         break ;
 
       default :  
         return  -EINVAL;
     }
     return  ret;
 
}
 
/*文件操作结构体*/
static  const  struct  file_operations mem_fops =
{
   .owner = THIS_MODULE,
   .open = mem_open,
   .release = mem_release,
   .ioctl = memdev_ioctl,
};
 
/*设备驱动模块加载函数*/
static  int  memdev_init( void )
{
   int  result;
   int  i;
 
   dev_t devno = MKDEV(mem_major, 0);
 
   /* 静态申请设备号*/
   if  (mem_major)
     result = register_chrdev_region(devno, 2,  "memdev" );
   else   /* 动态分配设备号 */
   {
     result = alloc_chrdev_region(&devno, 0, 2,  "memdev" );
     mem_major = MAJOR(devno);
   }  
   
   if  (result < 0)
     return  result;
 
   /*初始化cdev结构*/
   cdev_init(&cdev, &mem_fops);
   cdev.owner = THIS_MODULE;
   cdev.ops = &mem_fops;
   
   /* 注册字符设备 */
   cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
    
   /* 为设备描述结构分配内存*/
   mem_devp = kmalloc(MEMDEV_NR_DEVS *  sizeof ( struct  mem_dev), GFP_KERNEL);
   if  (!mem_devp)     /*申请失败*/
   {
     result =  - ENOMEM;
     goto  fail_malloc;
   }
   memset (mem_devp, 0,  sizeof ( struct  mem_dev));
   
   /*为设备分配内存*/
   for  (i=0; i < MEMDEV_NR_DEVS; i++) 
   {
         mem_devp[i].size = MEMDEV_SIZE;
         mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
         memset (mem_devp[i].data, 0, MEMDEV_SIZE);
   }
     
   return  0;
 
   fail_malloc: 
   unregister_chrdev_region(devno, 1);
   
   return  result;
}
 
/*模块卸载函数*/
static  void  memdev_exit( void )
{
   cdev_del(&cdev);    /*注销设备*/
   kfree(mem_devp);      /*释放设备结构体内存*/
   unregister_chrdev_region(MKDEV(mem_major, 0), 2);  /*释放设备号*/
}
 
MODULE_AUTHOR( "David Xie" );
MODULE_LICENSE( "GPL" );
 
module_init(memdev_init);
module_exit(memdev_exit);

 

.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef _MEMDEV_H_
#define _MEMDEV_H_
 
#include <linux/ioctl.h>
 
#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 190   /*预设的mem的主设备号*/
#endif
 
#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 2    /*设备数*/
#endif
 
#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 4096
#endif
 
/*mem设备描述结构体*/
struct  mem_dev                                     
{                                                        
   char  *data;                      
   unsigned  long  size;       
};
 
/* 定义幻数 */
#define MEMDEV_IOC_MAGIC  'k'
 
/* 定义命令 */
#define MEMDEV_IOCPRINT   _IO(MEMDEV_IOC_MAGIC, 1)
#define MEMDEV_IOCGETDATA _IOR(MEMDEV_IOC_MAGIC, 2, int)
#define MEMDEV_IOCSETDATA _IOW(MEMDEV_IOC_MAGIC, 3, int)
 
#define MEMDEV_IOC_MAXNR 3
 
#endif /* _MEMDEV_H_ */

 

Makefile

?
1
2
3
4
5
6
7
8
9
10
11
12
13
ifneq ($(KERNELRELEASE),)
 
obj-m := memdev.o
 
else
     
KDIR := /forlinux/linux-3.0.1
all:
     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*
 
endif

 

测试程序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
 
#include "memdev.h"  /* 包含命令定义 */
 
int  main()
{
     int  fd = 0;
     int  cmd;
     int  arg = 0;
     char  Buf[4096];
     
     
     /*打开设备文件*/
     fd = open( "/dev/memdev0" ,O_RDWR);
     if  (fd < 0)
     {
         printf ( "Open Dev Mem0 Error!\n" );
         return  -1;
     }
     
     /* 调用命令MEMDEV_IOCPRINT */
     printf ( "<--- Call MEMDEV_IOCPRINT --->\n" );
     cmd = MEMDEV_IOCPRINT;
     if  (ioctl(fd, cmd, &arg) < 0)
         {
             printf ( "Call cmd MEMDEV_IOCPRINT fail\n" );
             return  -1;
     }
     
     
     /* 调用命令MEMDEV_IOCSETDATA */
     printf ( "<--- Call MEMDEV_IOCSETDATA --->\n" );
     cmd = MEMDEV_IOCSETDATA;
     arg = 2007;
     if  (ioctl(fd, cmd, &arg) < 0)
         {
             printf ( "Call cmd MEMDEV_IOCSETDATA fail\n" );
             return  -1;
     }
 
     
     /* 调用命令MEMDEV_IOCGETDATA */
     printf ( "<--- Call MEMDEV_IOCGETDATA --->\n" );
     cmd = MEMDEV_IOCGETDATA;
     if  (ioctl(fd, cmd, &arg) < 0)
         {
             printf ( "Call cmd MEMDEV_IOCGETDATA fail\n" );
             return  -1;
     }
     printf ( "<--- In User Space MEMDEV_IOCGETDATA Get Data is %d --->\n\n" ,arg); 
     
     close(fd);
     return  0; 
}
【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
|
1月前
|
Shell Linux C语言
【Shell 命令集合 设备管理 】Linux 创建设备文件 MAKEDEV命令 使用指南
【Shell 命令集合 设备管理 】Linux 创建设备文件 MAKEDEV命令 使用指南
35 0
|
1月前
|
监控 Shell Linux
【Shell 命令集合 网络通讯 】Linux 分析串口的状态 statserial命令 使用指南
【Shell 命令集合 网络通讯 】Linux 分析串口的状态 statserial命令 使用指南
33 0
|
1月前
|
监控 Linux Shell
【Shell 命令集合 网络通讯 】Linux管理终端设备的登录过程 getty命令 使用指南
【Shell 命令集合 网络通讯 】Linux管理终端设备的登录过程 getty命令 使用指南
34 0
|
1月前
|
安全 Shell Linux
【Shell 命令集合 网络通讯 】Linux 打开终端设备 mingetty命令 使用指南
【Shell 命令集合 网络通讯 】Linux 打开终端设备 mingetty命令 使用指南
39 0
|
2天前
|
编解码 Linux 数据安全/隐私保护
linux工具之curl与wget高级使用
linux工具之curl与wget高级使用
|
10天前
|
Linux Go
Linux命令Top 100驱动人生! 面试必备
探索Linux命令不再迷茫!本文分10部分详解20个基础命令,带你由浅入深掌握文件、目录管理和文本处理。 [1]: <https://cloud.tencent.com/developer/article/2396114> [2]: <https://pan.quark.cn/s/865a0bbd5720> [3]: <https://yv4kfv1n3j.feishu.cn/docx/MRyxdaqz8ow5RjxyL1ucrvOYnnH>
64 0
|
16天前
|
网络协议 Linux SDN
虚拟网络设备与Linux网络协议栈
在现代计算环境中,虚拟网络设备在实现灵活的网络配置和隔离方面发挥了至关重要的作用🔧,特别是在容器化和虚拟化技术广泛应用的今天🌐。而Linux网络协议栈则是操作系统处理网络通信的核心💻,它支持广泛的协议和网络服务🌍,确保数据正确地在网络中传输。本文将深入分析虚拟网络设备与Linux网络协议栈的关联,揭示它们如何共同工作以支持复杂的网络需求。
|
17天前
|
存储 缓存 固态存储
Linux设备全览:从字符到块,揭秘每种设备的秘密
在Linux的世界里,设备是构成系统的基础,它们使得计算机能够与外界互动。Linux设备可以大致分为几种类型,每种类型都有其独特的特性和用途。🌌让我们一起探索这些设备类型及其特性。
|
22天前
|
Prometheus 监控 数据可视化
linux分析方法与技巧
【4月更文挑战第3天】在Linux环境中,进行日志分析和系统性能分析的关键方法包括:使用`cat`, `less`, `tail`查看和过滤日志,`logrotate`管理日志文件,`rsyslog`或`syslog-ng`聚合日志,以及通过`top`, `mpstat`, `pidstat`, `free`, `iostat`, `netstat`, `strace`, `sar`, `dstat`等工具监控CPU、内存、磁盘I/O和网络。对于高级分析,可利用Brendan Gregg的性能工具,以及Grafana、Prometheus等可视化工具。
18 2
linux分析方法与技巧
|
23天前
|
Linux
Linux驱动运行灯 Heartbeat
Linux驱动运行灯 Heartbeat
10 0