Linux v6.6 · 개념과 코드 읽기

드라이버 초기화: 코드를 등록하는 것과 장치를 찾는 것

이 코드는 어떤 문제를 푸나요?

부팅 중 driver_init은 장치 모델의 공통 기반을 준비합니다. 그 위에서 각 드라이버는 자신이 속한 버스와 연산을 등록하며, 버스는 이미 존재하거나 새로 나타난 장치와 연결을 시도합니다. 아래 driver_register 전체는 개별 드라이버 등록을 설명합니다. 공통 기반을 만드는 초기화 함수와 개별 하드웨어 probe를 같은 단계로 부르지 않는 것이 출발점입니다.

읽을 범위: v6.6 · drivers/base/driver.c · driver_register 222–258행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

bus

장치와 드라이버를 분류하고 맞는 조합을 찾는 공통 규칙을 제공합니다. 꼭 물리적인 외부 커넥터만 뜻하는 용어는 아닙니다.

device와 driver

device는 발견되거나 설명된 장치 인스턴스이고 driver는 이를 다루는 구현입니다. 둘의 수와 수명은 서로 다를 수 있습니다.

sysfs 그룹

드라이버 상태나 설정 속성을 사용자 공간에 보여 주는 묶음입니다. 등록 실패 때 버스 등록까지 되돌려 일관된 상태를 유지합니다.

deferred probe

의존하는 자원이 아직 준비되지 않았으면 장치 probe를 나중에 다시 시도할 수 있습니다. 드라이버 코드가 등록됐다는 사실과 모든 장치가 준비됐다는 사실은 다릅니다.

처음 읽을 때

드라이버를 등록했다고 장치를 무조건 하나 만든다고 생각하지 마십시오. 등록된 구현과 이미 존재하는 device 사이의 매칭이 그다음 연결 고리입니다.

더 깊이 살펴볼 때

버스 메서드와 드라이버 메서드가 중복되는 경우의 경고, 이름 중복 실패, sysfs 그룹 실패에 따른 롤백을 나누어 보십시오. 성공한 등록의 부수 효과와 실패 시 남겨도 되는 상태를 구분하는 연습이 됩니다.

그림으로 보는 변화

드라이버 초기화: 코드를 등록하는 것과 장치를 찾는 것의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 버스와 이름을 확인합니다

버스가 준비됐는지와 같은 이름의 드라이버가 이미 있는지 검사합니다.

화살표는 등록 전제 검사의 순서입니다.

2. 드라이버를 설치합니다

버스에 드라이버를 넣고 sysfs 속성 그룹을 추가합니다.

화살표는 드라이버 구현이 공통 장치 모델에 연결되는 관계입니다.

3. 등록 사실을 알립니다

성공하면 사용자 공간에 추가 이벤트를 보내고 지연된 probe의 대기 정책을 갱신합니다.

화살표는 등록 통지이며 모든 장치의 probe 완료를 뜻하지 않습니다.

driver_register를 한 줄씩 읽기

줄 번호는 v6.6 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	if (!bus_is_registered(drv->bus)) {
		pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n",
			   drv->name, drv->bus->name);
		return -EINVAL;
	}

	if ((drv->bus->probe && drv->probe) ||
	    (drv->bus->remove && drv->remove) ||
	    (drv->bus->shutdown && drv->shutdown))
		pr_warn("Driver '%s' needs updating - please use "
			"bus_type methods\n", drv->name);

	other = driver_find(drv->name, drv->bus);
	if (other) {
		pr_err("Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EBUSY;
	}

	ret = bus_add_driver(drv);
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret) {
		bus_remove_driver(drv);
		return ret;
	}
	kobject_uevent(&drv->p->kobj, KOBJ_ADD);
	deferred_probe_extend_timeout();

	return ret;
}
int driver_register(struct device_driver *drv)

등록할 device_driver를 받아 공통 장치 모델에 연결합니다.

	int ret;

단계별 반환 상태를 저장합니다.

	struct device_driver *other;

이름이 중복되는 다른 드라이버를 찾을 때 사용할 포인터입니다.

	if (!bus_is_registered(drv->bus)) {

이 드라이버가 지정한 버스가 먼저 등록됐는지 확인합니다.

		pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n",

버스 기반이 준비되지 않았다는 오류 문구를 출력합니다.

			   drv->name, drv->bus->name);

어떤 드라이버와 버스 조합이 문제인지 이름을 전달합니다.

		return -EINVAL;

기반 없는 버스에 드라이버를 등록하지 않고 오류를 반환합니다.

	if ((drv->bus->probe && drv->probe) ||

버스와 드라이버가 probe 메서드를 동시에 지정한 경우를 검사합니다.

	    (drv->bus->remove && drv->remove) ||

remove 메서드도 두 곳에 중복 지정됐는지 검사합니다.

	    (drv->bus->shutdown && drv->shutdown))

shutdown 중복까지 OR로 묶어 하나라도 해당하면 경고합니다.

		pr_warn("Driver '%s' needs updating - please use "

오래된 메서드 사용 방식을 갱신하라는 경고를 시작합니다.

			"bus_type methods\n", drv->name);

버스 메서드를 사용하라는 설명과 드라이버 이름을 출력합니다. 경고만 하고 아래 검사는 계속합니다.

	other = driver_find(drv->name, drv->bus);

동일 버스에 같은 이름의 드라이버가 이미 등록됐는지 찾습니다.

	if (other) {

중복 드라이버를 찾았는지 확인합니다.

		pr_err("Error: Driver '%s' is already registered, "

같은 이름으로 이중 등록하려 했다는 오류를 출력합니다.

			"aborting...\n", drv->name);

문제의 드라이버 이름과 중단 문구를 완성합니다.

		return -EBUSY;

이름 충돌 때문에 -EBUSY를 반환합니다.

	ret = bus_add_driver(drv);

드라이버를 버스 관리에 추가합니다. 매칭과 연결 작업은 버스 계층으로 이어집니다.

		return ret;

실패했으면 속성 그룹을 추가하지 않고 오류를 반환합니다.

	ret = driver_add_groups(drv, drv->groups);

드라이버가 제공한 sysfs 속성 그룹을 추가합니다.

	if (ret) {

속성 그룹 등록에 실패했는지 확인합니다.

		bus_remove_driver(drv);

부분 등록 상태를 남기지 않도록 앞서 한 버스 등록을 되돌립니다.

		return ret;

속성 그룹 단계의 오류를 반환합니다.

	kobject_uevent(&drv->p->kobj, KOBJ_ADD);

드라이버 추가를 KOBJ_ADD 이벤트로 사용자 공간에 알립니다.

	deferred_probe_extend_timeout();

새 드라이버가 의존 자원을 제공할 수 있으므로 지연된 probe의 시간 정책을 갱신합니다.

	return ret;

정상 등록 결과를 반환합니다.

함께 생각해 볼 질문

driver_init과 driver_register는 같은 함수인가요?

아닙니다. 앞은 장치 모델의 공통 기반 초기화, 뒤는 개별 드라이버 등록에 사용됩니다.

sysfs 속성 등록이 실패하면 버스 등록은 남기나요?

이 함수는 bus_remove_driver로 앞선 버스 등록을 되돌린 뒤 오류를 반환합니다.

드라이버 등록 성공이 장치 동작 성공인가요?

아닙니다. 각 장치 매칭과 probe, 의존 자원 준비가 별도로 필요합니다.

출처와 읽은 범위

Linux stable v6.6 · drivers/base/driver.c

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑