DEVSTAT(9)

명칭
devstat, devstat_add_entry, devstat_end_transaction, devstat_end_transaction_buf, devstat_remove_entry, devstat_start_transaction - 디바이스 통계의 기록을 위한 커널 인터페이스

서식
<sys/devicestat.h> void devstat_add_entry(struct devstat *ds, const char *dev_name, int unit_number, u_int32_t block_size, devstat_support_flags flags, devstat_type_flags device_type, devstat_priority priority) void devstat_remove_entry(struct devstat *ds) void devstat_start_transaction(struct devstat *ds) void devstat_end_transaction(struct devstat *ds, u_int32_t bytes, devstat_tag_type tag_type, devstat_trans_flags flags) void devstat_end_transaction_buf(struct devstat *ds, struct buf *bp)

해설
devstat 하부조직은, 그 명칭이 암시하는 것처럼, 디바이스 통계를 기록하기 위한 인터페이스입니다. 이 목적은, 적당히 상세한 통계 정보를 기록하면서, 기록에 사용하는 CPU 시간을 최소로 한다고 하는 것입니다. 따라서, devstat 의 코드의 커널내의 부분에서는, 실제의 통계적인 계산은 행해지고 있지 않습니다. 대신에, 이것은 유저 프로그램이 취급하도록(듯이) 남아 있습니다.

devstat_add_entry() 하 devstat 하부조직에 디바이스를 등록합니다. 호출측은 이 함수의 호출 전에, 이미 할당 0 로 클리어 된 devstat 구조체를 가지고 있는 것을 기대되고 있습니다. devstat_add_entry() (은)는 몇개의 인수를 취합니다.

ds  클라이언트에 의해 할당 0 으로 클리어 된, devstat 구조체입니다.

dev_name
    디바이스의 이름입니다. 예를 들면 da, cd, sa 입니다.

unit_number
    디바이스 유니트 번호입니다.

block_size
    서포트되고 있는 경우에는, 디바이스의 블록 사이즈입니다. 디바이스가 블록 사이즈를 서포트하고 있지 않는 경우, 또는 devstat 리스트에 그 디바이스가 추가되는 시점에서는 블록 사이즈가 알지 않은 경우에는, 0 으로 설정되어야 합니다.

flags
    디바이스에 의해 조작이 서포트되고 있을까 서포트되어 있지 않은가를 나타낸다 플래그입니다. 자세한 것은 이하를 참조해 주세요.

device_type
    디바이스의 형태입니다. 이것은 3 개의 부분, 기본적인 디바이스의 형태 (예를 들면, 직접 액세스, CDROM, 차례차례 액세스), 인터페이스의 형태 (IDE, SCSI 또는 그 외) 및 통과하는 디바이스를 나타내기 위한 파스스르후라그에, 분할됩니다. 완전한 형태의 리스트는 이하를 참조해 주세요.

priority
    디바이스의 우선도입니다. 우선도는 디바이스의 devstat 리스트 중(안)에서 어떻게 디바이스를 줄서 바꿀까를 결정하기 위해서(때문에) 사용됩니다. 디바이스는 최초로 우선도 (비싼 (분)편으로부터 낮은 (분)편)에 의해, 그리고 아탓치 된 차례로 따라 줄서 바꿀 수 있습니다. 이용 가능한 우선도의 완전한 리스트는 이하를 참조해 주세요.

devstat_remove_entry() 하 devstat 하부조직으로부터 디바이스를 삭제합니다. 이것은 인수로서 바로 그 디바이스의 devstat 구조몸을 잡습니다. devstat 세대 번호는 늘려지고 디바이스의 수는 줄여집니다.

devstat_start_transaction() 하 devstat 하부조직에 처리의 개시를 등록합니다. 개개의 처리의 개시에 Busy 카운트가 늘려집니다. 디바이스가 아이돌로부터 Busy로 옮겼을 때에는, 시스템 uptime 가 devstat 구조체의 start_time 필드에 기록됩니다.

devstat_end_transaction() 하 devstat 하부조직에 처리의 종료를 등록합니다. 이것은 4 개의 인수를 취합니다.

ds  바로 그 디바이스를 위한 devstat 구조체입니다.

bytes
    이 처리로 전송 된 바이트수입니다.

tag_type
    처리의 태그의 형태입니다. 태그의 형태는 이하를 참조해 주세요.

flags
    그 처리가 독포함이었는가, 기록이었는가, 또는 전송 된 데이터가 없었던 것일까를 나타내는 처리 플래그입니다.

devstat_end_transaction_buf() (은)는, biodone()의 준비가 갖추어지고 있다 struct buf (으)로부터 모든 정보를 꺼내기 위한, devstat_end_transaction() (을)를 위한 나팔입니다.

devstat 구조체는 이하의 필드로 구성되어 있습니다.

dev_links
    개개의 devstat (은)는 등록되었을 때에 링크 된 리스트에 놓여집니다. dev_links 필드에는 devstat 구조체의 리스트안의 다음의 엔트리에의 포인터가 들어갑니다.

device_number
    디바이스 번호는, 개개의 디바이스를 위한 일의인 식별자입니다. 디바이스 번호는, 개개의 새로운 디바이스가 등록될 때 마다 늘려집니다. 현재는 디바이스 번호는 단순한 32 비트 정수입니다만, 40 억개를 넘는다 디바이스 도착 이벤트를 가지는 시스템이 있으면, 확장할지도 모릅니다.

device_name
    디바이스 명칭은 드라이버 등록에 의해 주어지는 캐릭터 라인이며, 자기 자신을 식별하기 위해서 사용할 수 있습니다 (예를 들면 “da”, “cd”, “sa”, 등).

unit_number
    유니트 번호는 바로 그 주변장치의 드라이버 특유의 실체를 식별합니다.

bytes_written
    이것은 그 디바이스에 이미 쓰기바이트수입니다. 이 수는 현재는 부호 없음 64 비트 정수입니다. 32 비트의 정수를 사용했을 경우에는 시스템에 따라서는 곧바로 카운터가 한층 해 버린다고 하는 문제를, 이것에 의해 회피할 수 있다고 기대하고 있습니다.

bytes_read
    이것은 그 디바이스로부터 이미 독 붐비어진 바이트수입니다.

bytes_freed
    이것은 그 디바이스상의 이미 해방/소거된 바이트수입니다.

num_reads
    이것은 그 디바이스로부터의 독포함 회수입니다.

num_writes
    이것은 그 디바이스에의 기록 회수입니다.

num_frees
    이것은 그 디바이스상의 해방/소거 조작의 회수입니다.

num_other
    이것은 그 디바이스에의 독포함도 기록도 아닌 처리의 회수입니다. 예를 들면, SCSI 드라이버는 자주 테스트 유니트 레이디 명령을 SCSI 디바이스에 보냅니다. 그 테스트 유니트 레이디 명령은 데이터를 완전히 독 붐비어 또는 기록선. 이것은 단지 그 상태를 돌려주게 하는 만큼 지나지 않습니다.

busy_count
    이것은 그 디바이스를 위한 현재 미해결의 처리의 수입니다. 이것은 0 을 결코 밑돌아야 하는 것이 아니고, 아이돌의 디바이스에서는 0 이 되어야 합니다. 이러한 상태중 한쪽이 진이 아닌 경우에는, 클라이언트의 코드의 devstat_start_transaction() (와)과 devstat_end_transaction() 의 호출하는 방법에 문제가 있는 것을 나타내고 있습니다. 개개의 처리에는 다만 1 개의 처리 개시 이벤트가 있어야 하는 것이어, 각 처리에 대해서 1 개의 처리 종료 이벤트가 있어야 합니다.

block_size
    그 디바이스가 블록 사이즈를 가지고 있는 경우에는, 이것은 그 디바이스의 블록 사이즈입니다.

tag_types
    이것은 디바이스에 보내진 여러가지 태그의 형태의 수를 기록하기 위한 카운터의 배열입니다. 태그의 형태의 리스트는 이하를 참조해 주세요.

dev_creation_time
    이것은 그 디바이스가 등록되었을 때의 getmicrotime() 에 의해 보고되는 시간입니다

busy_time
    이것은, 디바이스의 Busy 카운트가 0 보다 컸던 시간의 양입니다. 이것은 Busy 카운트가 0 으로 돌아왔을 때에 마셔 갱신됩니다.

start_time
    이것은 그 디바이스의 Busy 카운트가 0 에서 1 으로 옮겼을 때의 getmicrouptime() 에 의해 보고되는 시간입니다

last_comp_time
    이것은 처리가 완전하게 끝났을 때의 getmicrouptime() 에 의해 보고되는 시간입니다 이것은 디바이스 Busy 시간을 계산하기 위해서 start_time (와)과 함께 사용됩니다.

flags
    이러한 플래그는 개개의 디바이스에 의해, 어느 통계 측정이 서포트 되고 있는지를 나타냅니다. 이러한 플래그는 본래는, 통계를 해독하는 유저측의 프로그램의 보조로서 일하는 것을 의도되고 있습니다.

device_type
    이것은 디바이스의 형태입니다. 이것은 3 개의 부분으로부터 구성되어 있습니다. 디바이스의 형태 (예를 들면, 직접 액세스, CDROM, 차례차례 액세스, 등), 인터페이스 (IDE, SCSI 또는 그 외) 및 바로 그 디바이스가 파스스르드라이바인지 어떤지, 입니다. 디바이스의 형태의 완전한 리스트는 이하를 참조해 주세요.

priority
    이것은 우선도입니다. 이것은 디바이스를 devstat 리스트의 어디에 삽입하는지를 결정하기 위해서(때문에) 사용되는 최초의 파라미터입니다. 2 번째의 파라미터는 아탓치의 차례입니다. 이용 가능한 우선도의 리스트는 이하를 참조해 주세요.

개개의 디바이스는 디바이스의 형태가 주어집니다. 파스스르데바이스는 인터페이스를 공급하기 위한 디바이스와 같은 기초적인 디바이스의 형태와 인터페이스를 가집니다만, 파스스르후라그도 설정되어 있습니다. 기본의 디바이스의 형태는 SCSI 의 디바이스 제품번호호로 일치하고 있습니다. 그 때문에 SCSI 주변장치에서는, 문의로부터 돌려주어진 디바이스의 형태는, 통상, SCSI 인터페이스의 형태라고도 해 적절하면 파스스르후라그로 OR 됩니다. 디바이스의 형태의 플래그는 이하대로입니다.

    typedef enum {
    	DEVSTAT_TYPE_DIRECT	= 0x000,
    	DEVSTAT_TYPE_SEQUENTIAL	= 0x001,
    	DEVSTAT_TYPE_PRINTER	= 0x002,
    	DEVSTAT_TYPE_PROCESSOR	= 0x003,
    	DEVSTAT_TYPE_WORM	= 0x004,
    	DEVSTAT_TYPE_CDROM	= 0x005,
    	DEVSTAT_TYPE_SCANNER	= 0x006,
    	DEVSTAT_TYPE_OPTICAL	= 0x007,
    	DEVSTAT_TYPE_CHANGER	= 0x008,
    	DEVSTAT_TYPE_COMM	= 0x009,
    	DEVSTAT_TYPE_ASC0	= 0x00a,
    	DEVSTAT_TYPE_ASC1	= 0x00b,
    	DEVSTAT_TYPE_STORARRAY	= 0x00c,
    	DEVSTAT_TYPE_ENCLOSURE	= 0x00d,
    	DEVSTAT_TYPE_FLOPPY	= 0x00e,
    	DEVSTAT_TYPE_MASK	= 0x00f,
    	DEVSTAT_TYPE_IF_SCSI	= 0x010,
    	DEVSTAT_TYPE_IF_IDE	= 0x020,
    	DEVSTAT_TYPE_IF_OTHER	= 0x030,
    	DEVSTAT_TYPE_IF_MASK	= 0x0f0,
    	DEVSTAT_TYPE_PASS	= 0x100
    } devstat_type_flags;

디바이스는 그것들에 관련지을 수 있었던 우선도를 가지고 있어, devstat 리스트의 대체로 어디에 놓여지는지를 제어합니다. 우선도는 이하대로입니다.

    typedef enum {
    	DEVSTAT_PRIORITY_MIN	= 0x000,
    	DEVSTAT_PRIORITY_OTHER	= 0x020,
    	DEVSTAT_PRIORITY_PASS	= 0x030,
    	DEVSTAT_PRIORITY_FD	= 0x040,
    	DEVSTAT_PRIORITY_WFD	= 0x050,
    	DEVSTAT_PRIORITY_TAPE	= 0x060,
    	DEVSTAT_PRIORITY_CD	= 0x090,
    	DEVSTAT_PRIORITY_DISK	= 0x110,
    	DEVSTAT_PRIORITY_ARRAY	= 0x120,
    	DEVSTAT_PRIORITY_MAX	= 0xfff
    } devstat_priority;

개개의 디바이스는 무슨 조작이 서포트되고 있을까 서포트되어 있지 않은 것인지를 나타내는, 거기에 관련지을 수 있었던 플래그를 가지고 있습니다. devstat_support_flags 의 값은 이하대로입니다.

DEVSTAT_ALL_SUPPORTED
    디바이스에 의해 모든 통계의 형태가 서포트되고 있습니다.

DEVSTAT_NO_BLOCKSIZE
    이 디바이스는 블록 사이즈를 가지고 있지 않습니다.

DEVSTAT_NO_ORDERED_TAGS
    이 디바이스는 순서 태그 (ordered tag)를 서포트하고 있지 않습니다.

DEVSTAT_BS_UNAVAILABLE
    이 디바이스는 블록 사이즈를 서포트하고 있습니다만, 현재는 이용할 수 없습니다. 이 플래그는 리모트 미디어의 드라이버로 자주(잘) 사용됩니다.

디바이스에의 처리는 3 개의 카테고리 중 어느 쪽인가에 분류됩니다. 이것은 devstat_end_transaction() 에 건네받는다 flags 에 표현되고 있습니다. 처리의 형태는 이하대로입니다.

    typedef enum {
    	DEVSTAT_NO_DATA	= 0x00,
    	DEVSTAT_READ	= 0x01,
    	DEVSTAT_WRITE	= 0x02,
    	DEVSTAT_FREE	= 0x03
    } devstat_trans_flags;

devstat_end_transaction() 의 tag_type 인수에는, 다음의 4 개의 값을 지정 가능합니다:

DEVSTAT_TAG_SIMPLE
    그 처리는 단순한 태그를 가지고 있었습니다.

DEVSTAT_TAG_HEAD
    이 처리는 큐 태그의 선두를 가지고 있었습니다.

DEVSTAT_TAG_ORDERED
    그 처리는 순서 태그를 가지고 있었습니다.

DEVSTAT_TAG_NONE
    그 디바이스는 태그를 서포트하지 않습니다.

태그의 형태의 값은 SCSI 의 태그의 정의의 하위 4 비트로 일치하고 있습니다. 예를 들면 CAM 에서는, CCB 의 tag_action 하지만 0xf 로 OR 하는 것으로써, devstat_end_transaction() 에 건네주는 태그의 형태를 판정합니다.

<sys/devicestat.h> 그리고 DEVSTAT_VERSION 매크로가 정의되고 있습니다. 이것은 devstat 하부조직의 현재의 버젼으로, devstat 통계에 액세스 하는 유저측 프로그램의 재컴파일이 요구되는 변경마다, 늘려져야 합니다. 유저측 프로그램은, 커널의 devstat 구조체와 동기 하고 있는지 어떤지를 결정하기 위해서(때문에), kern.devstat.version sysctl 변수를 통해 이 버젼을 사용합니다.

관련 항목
systat(1), devstat(3), iostat(8), rpc.rstatd(8), vmstat(8)

역사
devstat 통계 시스템은 FreeBSD 3.0 그리고 등장했습니다.

저자
Kenneth Merry <ken@FreeBSD.org>

버그
devstat 리스트 조작 코드 주위에서 spl() 보호가 필요할지도 모릅니다. 이것은, 예를 들면 누군가가 kern.devstat.all sysctl 변수를 꺼내고 있는 동안에, 디바이스의 리스트가 변경되지 않는 것을 프로텍션하기 (위해)때문입니다.

현재의 devstat 의 구조에서는 정확하게 처리 마다의 시간을 측정하는 것이 불가능합니다. 유일한 능숙하게 살 것 같은 처리 마다의 정확한 시간 측정의 방법은, 처리마다 타임 스탬프를 기록하는 것입니다. 시스템의 퍼포먼스 및 각개의 처리를 위해서(때문에) 타임 스탬프를 보존하기 위한 공간 코스트에 부의 영향을 주기 (위해)때문에, 이 측정은 아마는 대부분(거의)의 사람들에게는 가치가 없는 것입니다.