设备驱动管理流程,操作系统高等命令行手艺

作者: 韦德国际1946  发布:2019-05-28

GNU/Linux命令行习于旧贯

  Linux的命令行格局具备强大的功效,对于熟悉的Linux系统管理员来讲,往往只须求经过种种技术,组合构成一条复杂的授命,从而成就用户职分。

一 驱动程序,操作系统,文件系统和应用程序之间的涉及

字符设备和块设备映射到操作系统中的文件系统,由文件系统向上提须求应用程序统1的接口用以访问设备。

Linux把设备便是文件,称为设备文件,通过对配备文件的读写操作完结对实际外设的操作。

图片 1

从驱动程序的角度来从下到上看档次结构,包括了硬件装置,设备驱动程序(中断管理程序,设备服务程序),文件系统和用户进度几个档次:

图片 2

内需通晓的多个概念:

设备号:

  • 主设备号:标志同一类设备,对应二个驱动程序
  • 从设备号:标志三个装置实例,从设备号使得区别的情理设备选拔同三个驱动程序。

设施文件:存在硬盘上的骨子里存在的文件,蕴含设备的名字,类型,设备号

亟待驾驭的四个关于驱动操作的数据结构:

  • file_operations:文件操作,各类进程对设施的拜会都会改变为对file_operations的访问,调用里面包车型客车操作函数指针;
  • file:张开的文书
  • inode:由基本在文件系统中意味文件

近些日子在调度1个关于OpenVPN的次第,由于是长途支持的之所以有些很想获得的气象一直不好找切入点,比方OpenVPN客户端连接服务器常规,虚拟IP地址也壹度分配了,tap设备已经打开并从未抱错,然则张开的tap设备不是tap0而是" ",也正是怎样都不曾,连个空格都不是,那是怎么回事呢?
     为了难点简化,将引起难题的代码从OpenVPN中切出来,获得一个从头到尾展开tap设备的代码:
int main(int argc, char *argv[])
{

差点全数的GNU/Linux程序都依据一些平等的命令行解释习于旧贯,程序的参数通常分为了两大类:选项(option)只怕有个别标注(flag)、别的参数。选项(option)主若是提要求程序一些周转上的取舍,而别的参数则一般是提供给程序运转的输入之类的值。遵照习于旧贯,选项平日有两种表达情势:

  那么一条复杂的Linux命令怎么着结合呢?上边来介绍多少个手艺。

贰 字符设备的登记

图片 3

现今,设备驱动注册成功,有相应的装置驱动程序和装置号与之对应。

    struct ifreq ifr;
    int fd, err;
      char *clonedev = "/dev/net/tun";
      if( (fd = open(clonedev , O_RDWR)) < 0 ) {
            perror("Opening /dev/net/tun");
            return fd;
      }
      memset(&ifr, 0, sizeof(ifr));
      ifr.ifr_flags  |= IFF_TUN;//或者IFF_TAP
    printf("1:%sn", ifr.ifr_name);
     if( (err = ioctl(fd, TUNSETIFF, &ifr)) < 0 ) {
            perror("ioctl(TUNSETIFF)");
            close(fd);
            return err;
      }
    printf("2:%sn", ifr.ifr_name);
      return fd;
}
编写翻译为test奉行后,开掘第三回打字与印刷出"tun0",符合规律,然后将此程序拷贝给长途的难点机器,却从未打字与印刷"tun0"。诸多想不到的主题素材都和种类有关,于是问到了对方的系统版本,由uname -a获得,发掘实际上它是叁个陆十几位的连串,于是安装了1个陆九位的Red Hat,版本是:2.6.9-78.EL x86_64GNU/Linux。运维的test是贰个在三拾位系统上编写翻译的次序。由于linux的陆十五人内审查管理34位程序提供了格外服务,且x86-6四系统也对3十一位的指令集和寄存器提供了最尾巴部分的相配,想象来说不应当出此难点的,在陆拾陆位系统上检讨到了/lib/libc以及/lib/ld-linux等33个人的系统库和链接器就一发坚决了“难点不应当有”的思想--615人系统相称3肆人程序的轻便性需求N多档期的顺序的支撑,机器指令包容了,操作系统层和编写翻译器就不要再担忧指令,操作系统只须要提供系统服务的相称就能够,编写翻译器大概什么都无需做,再往上就是系统库了,比如glibc就须要提供两套,为313位程序和陆12个人程序分别提供劳动。然则尽管如此“难点不应该有”,事实是难点确实出现了,机器指令是杰出的,操作系统也是相配的,而系统中确实也可以有两套libc和ld,那么难题出在哪个地方吗?
     10有89是tun的驱动不平常,于是在drivers/net/tun.c的tun_chr_ioctl那几个字符设备的ioctl函数中进入dump_stack()调用,编写翻译之,insmod之,然后重新试行test,通过dmesg查看日志,以下是Call Trace:
<ffffffffa02c65b9>{:tun:tun_chr_ioctl 0} <ffffffffa02c65dd>{:tun:tun_chr_ioctl 36}
<ffffffff8019c341>{chrdev_open 952} <ffffffff801a7c86>{sys_ioctl 1006}
<ffffffff8012b355>{dev_ifsioc 228} <ffffffff801c65a4>{compat_sys_ioctl 379}
<ffffffff801279f7>{sysenter_do_call 27}
中间有贰个dev_ifsioc很让人诡异,难道推行流不是由此sys_ioctl直接路由到tun_设备驱动管理流程,操作系统高等命令行手艺。chr_ioctl的啊?为啥还要有2个dev_ifsioc?最终只能看二.6.玖根本的代码了。
      寻觅到了以下一行:
HANDLE_IOCTL(TUNSETIFF, dev_ifsioc)
HANDLE_IOCTL的定义:
#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) },
那明明是想组织叁个ioctl_trans数组:
struct ioctl_trans {
    unsigned long cmd;
    ioctl_trans_handler_t handler;
    struct ioctl_trans *next;
};
以此数组提供了根本档次系统调用的陆12个人向三十一人的包容性,整个连串有着须要提供包容性的系统调用都会登记3个ioctl_trans,总来说之dev_ifsioc实际管理了TUNSETIFF这一个ioctl命令。6四位上的三十三位程序发起的ioctl系统调用被操作系统路由到了compat_sys_ioctl(具体原因一会儿说):
asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
    ...
    t = ioctl32_hash_table[ioctl32_hash (cmd)];

短格局:日常是由八个“-”加上三个字母组合而成。这种样式的益处是输入快速。

  使用输入/输出重定向

三 设备的开垦

配备注册成功后,能够展开二个器械,那时候调用系统调用open()函数,经过一多种的调用,最终会调用chrdev_open()函数进行实际的开采操作,其重点流程为:

图片 4

道具注册张开完结后,需求对其张开种种操作,外部设备的操作有二个特征正是操作时间较长,且操作时间不鲜明。

管理外部设备运作时,首要有两种方法:轮询和间断。

下边首要用介绍用中断的格局等待外设完毕操作,其利害攸关流程为:

图片 5

    while (t && t->cmd != cmd)
        t = t->next;
    if (t) {
        if (t->handler) {
            lock_kernel();
            error = t->handler(fd, cmd, arg, filp); //对于TUNSETIFF来讲,这里调用dev_ifsioc
            unlock_kernel();
            up_read(&ioctl32_sem);
        } else {
            up_read(&ioctl32_sem);
            error = sys_ioctl(fd, cmd, arg);
        }
    }
    ...
}
dev_ifsioc的落到实处如下,它假诺提供“包容性”服务,比如统一陆十四位和3二位的数据类型等:
static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
{
    struct ifreq ifr;
    struct ifreq32 __user *uifr32;
    ...
    mm_segment_t old_fs;
    int err;
   
    uifr32 = compat_ptr(arg); //调换陆十几人的unsigned long数据类型到3四个人的地点
    ...
    switch (cmd) {
    case SIOCSIFMAP:
        ...//不是大家关切的TUNSETIFF
    default: //对于TUNSETIFF,掉入了default,顺遂从uifr3贰所表示的313位地点处拷贝了ifr结构到根本
        if (copy_from_user(&ifr, uifr32, sizeof(*uifr32)))
            return -EFAULT;
        break;
    }
    old_fs = get_fs();
    set_fs (KERNEL_DS);
    err = sys_ioctl (fd, cmd, (unsigned long)&ifr); //1
    set_fs (old_fs);
    if (!err) {
        switch (cmd) {  //前边的case鲜明未有TUNSETIFF
        case SIOCGIFFLAGS:
        case SIOCGIFMETRIC:
        case SIOCGIFMTU:
        case SIOCGIFMEM:
        case SIOCGIFHWADDR:
        case SIOCGIFINDEX:
        case SIOCGIFADDR:
        case SIOCGIFBRDADDR:
        case SIOCGIFDSTADDR:
        case SIOCGIFNETMASK:
        case SIOCGIFTXQLEN:
            if (copy_to_user(uifr32, &ifr, sizeof(*uifr32)))
                return -EFAULT;
            break;
        case SIOCGIFMAP:
            ...//不是大家关切的TUNSETIFF
        }
    }
    return err;
}
注意“1”处的sys_ioctl调用使用的ifr的地方调用sys_ioctl,而ifr的地方明显只是三当中路变量,它存款和储蓄在提倡系统调用的长河的内核栈上,显明是贰个内核栈地址,综上说述,尽管sys_ioctl将实施流路由到了tun_chr_ioctl,而tun_chr_ioctl正确地将信息拷贝到了它的参数arg,数据也单独填充到了内核栈上,而不是当真的用户进度的地方。假使急需真正将数据拷贝到用户进度空间,大家须要在后头的switch中加二个case,这几个case即TUNSETIFF,那样结果就不易了。那明确是3个根本的bug,不通晓哪位家伙加了HANDLE_IOCTL(TUNSETIFF, dev_ifsioc)这么壹行,却遗忘了在dev_ifsioc中拍卖TUNSETIFF,那大致能够毫无疑问不是1人加的,有的时候光翻一下patchs确认一下。

长方式:平时是由四个“-”加上多少个单词组合而成。这种样式的利润是形象、好记、直观。

  在Linux命令行形式中,如若命令所需的输出不是根源键盘,而是来自钦命的公文,那正是输入重定向。同理,命令的输出也得以不显得在显示器上,而是写入到内定文件中,那便是输出重定向。

4 小结

这里大致计算了须臾间Linux管理外部设备的严重性流程,主要归纳了外部设备的挂号,张开和日常的操作。

亟需专注的知识点正是驱动装置模型的定义,在字符设备中位cdev。全体对配备的操作,都以在cdev的ops字段寻觅管理程序,在此之前将cdev映射道inode的i_cedv中,cdev的ops字段映射到道具文件file的f_op字段,那样对设备文件的操作就同样对配备的操作,这正是本文开首所验证的配备文件映射到文件系统的本色。

在外部设备的操作流程中,涉及到中断管理流程,首要指的是软中断,会在暂停1章详细商酌。

参考:

Linux操作系统一分配析PPT:驱动程序编写基础

图片 6

万般来说,一个主次读于那三种情势都支持。比如大繁多的先后都有这么的调用选项:“-h”和“――help”。一些精选需求精晓前面跟着的参数,比方“ls –s /”,这里在那之中的“/”就是贰个参数。

  接下去看看规范输入/输出重定向在结构一条Linux命令中的实际使用。

使用getopt_long函数来拍卖

  一.输入重定向和输出重定向

对于贰个命令行的分析管理是很单调乏味的办事,要求做多量的举例字符串的合作之类的操作,然则幸运的是,GNU C函数Curry面提供了四个函数能够使得这项职业变得轻巧得多。当然或然还是未有您想像的那么容易。getopt_long这几个函数就可见同期“精晓”长情势和短情势的参数。

  # wc home.txt

上边大家通过三个实例来读书这些函数的运用。

  第二条命令将文件aa.txt作为wc命令的输入,计算出aa.txt的行数、单词数和字符数。第叁条命令将ls命令的出口保存在3个名称叫home.txt的文件中。如若>符号前边的文书已存在,那么这一个文件将被重写。

只要大家要编写制定的叁个顺序需求处理以下多少个参数:

  2.并且使用输入和输出重定向

短形式    长形式             含义

-h       ――help           打印帮助信息

-s       ――server         服务器IP地址

-b       ――background     后台执行

  # iconv -f gb18030 -t utf-8 new-aa.txt

本文由韦德国际1946发布于韦德国际1946,转载请注明出处:设备驱动管理流程,操作系统高等命令行手艺

关键词: betvlctor

上一篇:Shell内置命令,命令电子书
下一篇:没有了