ioctl函数

一、什么是ioctl
  ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。
  ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数来控制设备的I/O通道。
  用户程序所作的只是通过命令码(cmd)告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

二、 ioctl如何实现
  在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事情。因为设备都是特定的,这里也没法说。

三、ioctl参数
1、用户空间,ioctl的调用具有如下原型:
int ioctl(int fd, unsigned long cmd, …);
其中fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。
2、驱动空间,ioctl方法的原型如下:
int (*ioctl) (struct inode * node, struct file *filp, unsigned int cmd, unsigned long arg);
1)inode和file:ioctl的操作有可能是要修改文件的属性,或者访问硬件。要修改文件属性的话,就要用到这两个结构体了,所以这里传来了它们的指针。
2)cmd:控制命令。
3)arg:补充参数。
在这里插入图片描述ioctl函数_第1张图片

Struct ifconf{
    int ifc_len;                 // 缓冲区的大小
    union{
        caddr_t ifcu_buf;        // input from user->kernel
        struct ifreq *ifcu_req;    // return of structures returned
    }ifc_ifcu;
};
#define  ifc_buf  ifc_ifcu.ifcu_buf    //buffer address
#define  ifc_req  ifc_ifcu.ifcu_req    //array of structures returned
#define  IFNAMSIZ  16
struct ifreq{
    char ifr_name[IFNAMSIZ];           // interface name, e.g., “le0”
    union{
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        short ifru_flags;
        int ifru_metric;
        caddr_t ifru_data;
    }ifr_ifru;
};
#include    
#include    
#include    
#include    
#include    
#include    

struct ifreq *get_ifreq();

int main(int argc, char **argv)
{
    struct ifreq *ifr, *tobefree;

    ifr = tobefree = get_ifreq();
    
    do {
        printf("%s\n", ifr->ifr_name);
        ifr++;
    } while (ifr->ifr_name[0] != 0);

    free(tobefree);

    exit(0);
}

struct ifreq *get_ifreq()
{
    int  sockfd, len, lastlen;
    char *buf;
    struct ifconf ifc;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    lastlen = 0;
    len = 40 * sizeof(struct ifreq);        /* initial buffer size guess */
    for ( ; ; ) {
        buf = malloc(len);
        ifc.ifc_len = len;
        ifc.ifc_buf = buf;
        if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
            if (errno != EINVAL || lastlen != 0) {
                perror("ioctl");
                exit(-1);
            }
        } else {
            if (ifc.ifc_len == lastlen) {
                break;                      /* success, len has not changed */
            }
            lastlen = ifc.ifc_len;
        }
        len += 10 * sizeof(struct ifreq);   /* increment */
        free(buf);
    }
    return ((struct ifreq *)ifc.ifc_buf);
}

你可能感兴趣的:(ioctl函数)