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

转自: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; 

}

时间: 2024-10-08 23:17:25

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

Linux高级字符设备之Poll操作

在用户程序中,select()和poll()也是与设备阻塞与非阻塞访问息息相关的,使用非阻塞I/O的应用程序通常会使用select和poll系统调用查询是否可对设备进行无阻塞的访问.select系统调用最终会引发设备驱动中的poll函数被执行. 一.select()系统调用: 用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程. 1.select()原型: int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set 

Linux高级字符设备驱动 poll方法(select多路监控原理与实现)

1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select系统调用用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程.      int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, const struct timeval *timeout)     Select系统调用(参数)     1)Maxfd:           文件描述符的范围,比

linux字符设备驱动--基本知识介绍

一.设备驱动的分类 1.字符设备 字符设备是指那些能一个字节一个字节读取数据的设备,如LED灯.键盘.鼠标等.字符设备一般需要在驱动层实现open().close().read().write().ioctl()等函数. 2.块设备 块设备与字符设备类似,一般是像磁盘一样的设备.在块设备中还可以容纳文件系统,并存储大量的信息.在linux系统中,进行块设备读写时,每次只能传输一个或者多个块.linux也可以让应用程序像访问字符设备一样访问块设备,一次只读取一个字节. 3.网络设备 网络设备主要负

Linux实现字符设备驱动的基础步骤

Linux应用层想要操作kernel层的API,比方想操作相关GPIO或寄存器,能够通过写一个字符设备驱动来实现. 1.先在rootfs中的 /dev/ 下生成一个字符设备.注意主设备号 和 从设备号.可用例如以下shell脚本生成: if [ ! -e audioIN ];then sudo mknod audioIN c 240 0 fi 生成的设备为 /dev/audioIN ,主设备号240,从设备号0. 2.写audioINdriver.ko ,audioINdriver.c 基本代码

字符设备驱动ioctl实现用户层内核层通信

测试代码实现 memdev.h #ifndef _MEMDEV_H_ #define _MEMDEV_H_ #include<linux/ioctl.h> #ifndef MEMDEV_MAJOR #define MEMDEV_MAJOR 0 #endif #ifndef MEMDEV_NR_DEVS #define MEMDEV_NR_DEVS 2 #endif #ifndef MEMDEV_SIZE #define MEMDEV_SIZE 4096 #endif struct mem_de

字符设备驱动(1)代码分析---之gpio_get_value()

在中断处理函数中,调用gpio_get_value/gpio_set_value()函数来获取/设置gpio端口的值,在这里简单分析一下内核的实现流程. tmp = gpio_get_value(S5PV210_GPH2(0)); #define gpio_get_value __gpio_get_value int __gpio_get_value(unsigned gpio) { struct gpio_chip *chip; int value; chip = gpio_to_chip(g

linux驱动学习(1)——字符设备驱动开发

(一)驱动程序介绍 (a)Linux驱动程序学习 知识结构: 1. Linux驱动程序设计模式(40%) 2. 内核相关知识(30%) 3. 硬件相关知识(30%) (b)驱动分类: ①字符设备: 字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现 open, close,read和 write 系统调用. ②块设备: 在大部分的 Unix 系统, 块设备不能按字节处理数据,只能一次传送一个或多个长度是512字节( 或一个更大的 2 次幂的数 )的整块数据,而Lin

Linux内核分析(五)----字符设备驱动实现

原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷,我们都会以虚拟的设备为例进行学习,所以大家不必害怕没有硬件的问题. 今天我们会分析到以下内容: 1.      字符设备驱动基础 2.      简单字符设备驱动实现 3.      驱动测试 l  字符设备基础 1.       字符设备描述结构 在linux2.6内核中,使用cdev结构体描述一

从Linux内核LED驱动来理解字符设备驱动开发流程

目录 博客说明 开发环境 1. Linux字符设备驱动的组成 1.1 字符设备驱动模块加载与卸载函数 1.2 字符设备驱动的file_operations 结构体中的成员函数 2. 字符设备驱动--设备号注册卸载 2.1 设备号注册 2.2 设备号注销 3. 字符设备驱动--文件操作 参考资料 示例代码 @(从Linux内核LED驱动来理解字符设备驱动开发流程) 博客说明 撰写日期 2018.12.08 完稿日期 2019.10.06 最近维护 暂无 本文作者 multimicro 联系方式 [