Linux 커 널 구동 모델 --- 장치 버스 구동

커 널 구동 모델
  • 구동 모델 이 무엇 입 니까
  • Linux 구동 모델
  • 구동 모델
  • dev 유형 --- struct 장치
  • bus 유형 --- struct bustype
  • drv 유형 --- struct devicedriver

  • 구동 에 관련 된 인터페이스
  • bus 관련
  • dev 관련
  • drv 관련

  • 총화
  • 후속
  • 구동 모델 이란 무엇 인가
    내 가 보기에 모델 은 일련의 사무 에 대해 추상 적 이 고 통일 적 이 며 관 리 를 하 는 것 이다.나타 나 는 차원 적 관계.한 회사 에 부서, 팀, 개인 같은 조직 관계 가 있 는 것 과 같다.그러면 이렇게 하 는 장점 은 바로 관리 하기 편리 하 다 는 것 이다.
    Linux 구동 모델
    리 눅 스 의 세계 에서 C 언어 를 극치 로 운용 하 는데 여기 서 는 단순히 구조 체 로 상상 해 서 는 안 되 고 데이터 구조 뒤의 의 미 를 체득 해 야 하 며 구조 체 유형 으로 만 이해 해 서 는 안 된다.c + + 에 서 는 클래스 라 는 더 좋 은 표현 이 있 습 니 다.모든 유형 을 유형 으로 상상 하면 더 잘 이해 할 수 있다.그 중에서 구조 체 의 구성원 변 수 는 속성 으로 분류 되 는데 그 중에서 함수 포인터 류 는 이런 종류 가 가지 고 있 는 방법 과 비교 된다.한 인물 의 고유 혈 조 (속성) 와 이 인물 의 공격 스 킬 (방법) 을 비교 합 니 다.이런 구 조 는 리 눅 스에 서 흔히 볼 수 있다.
    구동 모형
    Linux 에서 가장 흔히 볼 수 있 는 구동 모델 은 바로 장치 (dev) - 버스 (bus) - 구동 (drv), 이런 모델 구조 이다.리 눅 스에 서 클래스 는 일반적으로 업무 의 추상 적 이 고 통용 되 는 공 통 된 내용 을 추출한다.장치 유형 은 이 장치 의 구체 적 인 통용 속성 을 설명 하 는 것 이 더 많다.bus 는 dev 와 drv 의 다리, 유대 입 니 다.dev 와 drv 의 관 계 는 바로 bus 로 연결 되 는 것 이다.drv 는 더 많은 방법 을 설명 합 니 다. 이런 장 치 는 그 가 어떤 기능 을 가지 고 있 는 지, 일반적으로 drv 에서 설명 합 니 다.
    dev bus drv 의 형식 은 kernel \ include \ linux \ \ device. h 파일 에 정 의 됩 니 다.
    dev 타 입 - struct device
    리 눅 스에 서 장 치 는 광범 위 한 개념 이지 특정한 실체 장 치 를 가리 키 는 것 이 아니다.추상 적 인 설비 이 므 로 실체 설비 로 취급 하지 마라.
    struct device {
         
     struct device  *parent;
     struct device_private *p;
     struct kobject kobj;
     struct bus_type *bus;  /* type of bus device is on */
     struct device_driver *driver; /* which driver has allocated this
            device */
     void  *platform_data; /* Platform specific data, device
            core doesn't touch it */
     void  *driver_data; /* Driver data, set and get with
            dev_set/get_drvdata */
            ....
    }
    struct device_private {
         
     struct klist klist_children;
     struct klist_node knode_parent;
     struct klist_node knode_driver;
     struct klist_node knode_bus;
     struct list_head deferred_probe;
     struct device *device;
    };
  • 그 중에서 가장 중요 한 몇 개의 구성원 변 수 는 * bus * driver 지침 으로 이 dev 와 연 결 된 버스 와 구동 을 가리킨다.
  • 이 * p 의 구성원 변수 도 있 습 니 다.이 list node 는 bus 가 관리 하 는 dev 링크 에 삽입 되 고 관리 되 며 drv 의 노드 도 drv 가 관리 하 는 dev 링크 에 삽입 되 어 drv 에 의 해 관리 된다.
  • 이 구조 체 에 따라 저 는 이 설비 가 어느 bus 에 속 하 는 지 알 수 있 고 제 구동 이 무엇 인지 알 수 있 습 니 다.
  • dev 의 name 은 kobj 의 구성원 변수 name 에 존재 합 니 다. 그 는 같은 name 을 사용 합 니 다.

  • bus 타 입 - struct bustype
    이곳 의 bus 역시 광범 위 한 개념 으로 cpu 의 실제 버스 가 아니 라 프로그램 에서 가상 으로 만들어 진 코드 구조 입 니 다.
    struct bus_type {
         
     const char  *name;
     const char  *dev_name;
     struct device  *dev_root;
     struct subsys_private *p;
     int (*match)(struct device *dev, struct device_driver *drv);
     int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
     int (*probe)(struct device *dev);
     }
     
     struct subsys_private {
         
     struct klist klist_devices;
     struct klist klist_drivers;
     struct bus_type *bus;
     }
     
  • match 방법 은 이 bus 에서 dev 와 drv 두 가지 가 일치 하 는 방법 입 니 다. 하 나 는 dev 이 고 하 나 는 drv 입 니 다. 그들 두 사람의 특정한 속성 만 맞 았 습 니 다. (보통 dev 와 drv 의 이름 을 일치 하 는 조건 으로 합 니 다) 그러면 우 리 는 이 dev 가 drv 와 일치 하면 probe 를 실행 하 는 방법 이 라 고 부 릅 니 다. 뒤의 코드 에서 소개 합 니 다.
  • bus 유형 에서 가장 중요 한 것 은 * p 라 는 구성원 변수 입 니 다.그 는 dev 링크 와 drv 링크 두 개 를 관리 했다.이렇게 버스 는 관리자 역할 을 한다.그 는 현재 그의 이 bus 가 어떤 설비 와 구동 을 가지 고 있 는 지 알 고 있다.

  • drv 타 입 - struct devicedriver
    drv 역시 광범 위 한 의미 에서 의 구동 으로 특정한 외부 장치 의 구동 이 아니다.여기 서도 추상 화 되 었 지만 구체 적 인 외부 장치 구동 은 반드시 이 데이터 구 조 를 바탕 으로 하 는 것 이다.약간 c + + 중국 과 외국 에서 구동 되 는 아버지 같은 느낌 이에 요.
     struct device_driver {
         
     const char  *name;
     struct bus_type  *bus;
     struct driver_private *p;
     int (*probe) (struct device *dev);
     }
     
     struct driver_private {
         
     struct kobject kobj;
     struct klist klist_devices;
     struct klist_node knode_bus;
     struct module_kobject *mkobj;
     struct device_driver *driver;
    };
  • * bus 에 의 하면 나의 이 구동 이 어느 bus 에 속 하 는 지 알 수 있다.
  • 똑 같이 p 가 있 고 p 안에 bus 노드 가 있 습 니 다. 그러면 bus 의 그 p 의 drv 링크 에 삽입 되 어 관 리 됩 니 다
  • 그 밖 에 dev 의 링크 가 있 는데 이 링크 는 이 구동 에 일치 하 는 모든 장 치 를 관리 하 는 데 사용 되 는 것 입 니 다. 왜 이런 구조 가 있 습 니까? 한 장치 에 하나의 구동 만 있어 야 하고 한 구동 은 여러 개의 장 치 를 가 질 수 있 습 니 다.여러 개의 동일 하거나 유사 한 장치 가 하나의 구동 을 공유 합 니 다.그 건 이해 할 수 있 을 거 야.

  • 구동 인터페이스
    등 록 된 인터페이스 마다 register 가 있 는데 그 와 대응 하 는 unregister 인터페이스 가 있 습 니 다. 예 를 들 어 int driverregister (struct device driver * drv) 와 그 에 게 void driver 가 있어 야 합 니 다.unregister (struct device driver * drv) 인터페이스.주로 자원 의 방출 등 관련 작업 에 사용 된다.
    버스 관련
    drv 와 dev 의 초기 화 는 모두 bus 와 관련 되 기 때문에 Liux 에서 bus 는 모두 초기 화 를 해 야 dev 와 drv 에 등 록 될 때 사용 할 수 있 습 니 다.인터페이스 정 의 는 \ \ drivers \ base \ bus. c int busregister(struct bus_type *bus)
    int bus_register(struct bus_type *bus)
    {
         
     int retval;
     struct subsys_private *priv;
     priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); //  bus p  
     priv->bus = bus;//p bus         bus
     bus->p = priv;//     bus p          p  
     /*    bus p      ,   dev   drv   */
     klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
     klist_init(&priv->klist_drivers, NULL, NULL);
     }

    dev 관련
    인 터 페 이 스 는 \ drivers \ base \ core. c 로 정의 되 며, 실 체 는 대부분 device 로 작 동 합 니 다.add 완성.아래 에 소 개 된 dev 등록 과정 은 bus 에 drv 가 등 록 된 상황 에서 dev 등록 함수 의 호출 과정 을 말 합 니 다. 만약 에 bus 에 drv 가 없다 면 호출 과정 은 이렇게 복잡 하지 않 습 니 다.만약 bus 가 일치 하 는 drv 가 없다 면 현재 dev 의 구동 이 없 거나 아직 등록 되 지 않 았 다 는 것 을 설명 합 니 다. 괜 찮 습 니 다. drv 가 등록 할 때 장 치 를 한 번 훑 어보 고 bus 의 probe 방법 을 실행 합 니 다.int device_register(struct device *dev)—》int device_add(struct device *dev)
    int device_add(struct device *dev)
    {
         
    if (dev->init_name) {
         // init_name       dev   
      dev_set_name(dev, "%s", dev->init_name);
      dev->init_name = NULL;
     }
     //            bus_add_device->klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
     //   dev  p bus     -》bus  p dev    , bus    。
     error = bus_add_device(dev);
      bus_probe_device(dev);
    }
    //      
    bus_probe_device(dev)-device_initial_probe(dev)-__device_attach(dev, true)-》ret = bus_for_each_drv(dev->bus, NULL, &data,__device_attach_driver)-int __device_attach_driver;
    //    --   bus  drv               dev          。         fn---   -》__device_attach_driver
    int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
           void *data, int (*fn)(struct device_driver *, void *))
    {
         
      while ((drv = next_driver(&i)) && !error)
      error = fn(drv, data);
    }
    __device_attach_driver(struct device_driver *drv, void *_data)
    {
         
     ret = driver_match_device(drv, dev);//    bus match  ,            ,bus      match     。drv->bus->match(dev, drv)
     if (ret == 0) {
         
      /* no match */
      return 0;
     }
     return driver_probe_device(drv, dev);
    }
    
    driver_probe_device(drv, dev);-really_probe(dev, drv);
    
    really_probe(struct device *dev, struct device_driver *drv)
    {
         
     dev->driver = drv;
     if (dev->bus->probe) {
         
      ret = dev->bus->probe(dev);
     }
     else if (drv->probe) {
         
      ret = drv->probe(dev);
     }
     //    ,dev p   drv     drv     p dev   , drv    。
     //    klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
     driver_bound(dev);
    }

    drv 관련
    마찬가지 로 아래 drv 의 등록 도 bus 위 dev 가 있 는 상황 에서 분석 합 니 다.drv 등록 함수 대부분 busadd_driver 완료.인터페이스 정 의 는 \ \ drivers \ base \ \ driver. c int driverregister(struct device_driver *drv)-》bus_add_driver(drv);
    int bus_add_driver(struct device_driver *drv)
    {
         
     struct bus_type *bus;
     struct driver_private *priv;
     priv = kzalloc(sizeof(*priv), GFP_KERNEL);//  drv       p
     klist_init(&priv->klist_devices, NULL, NULL);//   p dev  ,  dev     ,  dev        , drv     。
     priv->driver = drv;//p drv      drv
     drv->p = priv;//drv p         ,             p  drv         。
     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);// drv p   bus  ,  bus  p drv   , bus    ,   dev     。
     error = driver_attach(drv);
    }
    
    driver_attach-bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
    int __driver_attach(struct device *dev, void *data)
    {
         
     ret = driver_match_device(drv, dev);//     dev         ,  bus match        dev drv    。
     if (ret == 0) {
         
      /* no match */
      return 0;
     }
     if (!dev->driver)
      driver_probe_device(drv, dev);//       dev         ,   ,  bus probe      ,     drv probe,      dev         ,         。
    
    }

    bus_for_each_dev 는 drv 와 등록 할 때 유사 합 니 다. bus 의 모든 dev 를 가 져 와 서 이 드라이브 와 일치 합 니 다.일치 하 는 방법 은driver_attach
    총결산
    전체적으로 말 하면 리 눅 스에 있 는 코드 가 정말 많 습 니 다. 모두 이해 하 는 것 은 정말 불가능 합 니 다. 이 글 을 포함 하여 저도 주제 와 관련 이 없 는 코드 와 내용 을 많이 삭 제 했 습 니 다.예 를 들 어 코드 에 디 버 깅 과 관련 된 파일 시스템 과 관련 된 내용 이 많 습 니 다. 저 는 붙 이지 않 았 습 니 다. 이런 내용 은 주로 / sys / class / 디 렉 터 리 에서 의 차원 관계 관리 이기 때문에 본 고의 주제 와 큰 관련 이 없 기 때문에 코드 를 보 는 것 도 마찬가지 입 니 다. 너무 관련 된 것 이 아니 라 직접적 으로 생략 합 니 다. 경험 이 유한 하기 때 문 입 니 다.그리고 어떤 것 이 관련 되 고 어떤 것 이 부차적인 것 인지 어떻게 판단 하 는 지 경험 을 잘 쌓 아야 합 니 다. 모든 일 에는 과정 이 있 습 니 다. 점점 익숙해 지고 접촉 을 많이 하면 의식 이 생 길 것 입 니 다.
    후속
    처음에 공부 할 때 도 인터넷 에서 자 료 를 찾 아 다른 사람의 이 해 를 먼저 보고 대체적인 주 된 부분 을 만 진 다음 에 스스로 코드 를 보고 정확 한 이해 여 부 를 검증 했다.많은 자 료 를 본 후에 이론 구 조 는 명확 하 게 말 했 지만 마음속 에 의문 이 하나 있다. 이 물건 을 어디 에 쓰 면 좋 을 지.말하자면 이론 과 실제 의 결합 이 부족 하 다 는 것 이다.그래서 저 는 뒤에 이 구동 모델 의 인 스 턴 스 플랫폼 버스 의 활용 을 소개 하 는 글 을 쓸 것 입 니 다.이론 과 실례 의 결합 분석 은 너 로 하여 금 이 지식 점 을 더욱 잘 이해 하 게 할 것 이다.

    좋은 웹페이지 즐겨찾기