구)홈페이지 오탈자 보기
IT EXPERT, 리눅스 디바이스 드라이버

 

페이지오탈자 내용등록일
31

((p.31) 7번째줄)

커널을 보안한 후
==>
커널을 보완한 후

2006-10-251
37

((p.37) 마지막 문단 넷째줄)

초기 설정 상태를 그대로 따르면 별 문제가 된다.
==>
초기 설정 상태를 그대로 따르면 별 문제가 되지 않는다.

2006-10-251
44

((p.44) [그림 1-12]와 설명)

1) [그림 1-12] 프린터 공유기 케이블
2) 그래서 필자는 프린터 공유기 케이블을 이용하기를 권한다.
3) 프린터 확장 케이블과 모양이 비슷해서 ~ 반드시 프린터 공유기 케이블이라는
==>
원문이 맞다.  확장 또는 연장 케이블을 사용하면, 한쪽 끝의 모양이 프린터 포트에 맞는 모양이기 때문에 실험하기가 곤란하다. 그래서 필자는 프린터 공유기 케이블을 사용한다.

2006-10-251
44

((p.44) 주의 박스의 3~4번째줄)

그러므로 ...수 있다. 물론 프린터 포트에 흐르는 전류가 그리 높지 않기 때문에 LED가 동작하지 않으면(이런 경우는 거의 없지만) LED를 교체해 보기 바란다.
==>
따라서 ... 수 있다(물론 프린터 포트에 흐르는 전류가 그리 높지 않기 때문에 이런 경우는 거의 없지만). 그러므로 LED가 동작하지 않으면 LED를 교체해 보기 바란다.

2006-10-251
53

((p 53) 네번째 문단 두번째줄)

커널 2.6부터는 NPTL(Native POSIX Treading Library)과 NGPT(Next Generation Pthread Library)를 지원한다.
==>
커널 2.6부터는 NPTL(Native POSIX Treading Library)과 NGPT(Next Generation POSIX Threading Package)를 지원한다.

2006-10-251
255

(p55, [표2-2] 제목)

[표2-2] arc 디렉토리의 하부 디렉토리
=>
[표2-2] arch 디렉토리의 하부 디렉토리

2006-11-226
59

((p.59) 절 소개글)

디바이스 드라이버에 대해서 본격적으로 알아보고, 먼저 ...
==>
디바이스 드라이버에 대해서 본격적으로 알아본다. 먼저...

2006-10-251
65

((p 65) 밑에서 둘째줄)

드라이버와 디바이스 드라이버를 별도로
==>
디바이스와 디바이스 드라이버를 별도로

2006-10-251
67

((p.67) 두번째 문단 첫째줄)

기본적으로 구축된 디바이스 드라이버에는 보통 다음과 같은 요소를 포함한다.
==>
기본적으로 구축된 다비이스 드라이버에는 보통 다음과 같은 요소가 포함된다.

2006-10-251
83

((p.83) 세번째 문단 첫째줄)

파일명은 NULL 포인터로 끝나는 문자열이어야 하는데,
==>
파일명은 NULL 문자로 끝나는 문자열이어야 하는데,

부연설명) NULL character는 표준(ANSI/ISO 9899)에 의해 0을 값으로 지정하고 있는 반면 NULL pointer는 내부적인 값은 구현에 따라 달라질 수 있습니다. 따라서 NULL 포인터와 NULL 문자는 혼용하지 않는 것이 좋을 것 같습니다.

참고)
http://en.wikipedia.org/wiki/Null_character
http://en.wikipedia.org/wiki/Null_pointer

2006-10-251
84

((p.84) 첫째줄)

무정전 시스템
==>
무정지 시스템

2006-10-251
92

((p 92) 두번째 문단 넷째줄)

... 위치가 0x387로 지정된다. 두번째 인자가 SEEK_SET이므로 0x387은 ...
==>
... 위치가 0x378로 지정된다. 두번째 인자가 SEEK_SET이므로 0x378은 ...

2006-10-251
99

((p. 99) '설명' 블럭의 6번째줄)

해당 옵션을 지정하더라도 블록되지 않을 수 있다.
==>
해당 옵션을 지정하더라도 블록 될 수 있다.

2006-10-251
100

((p. 100) '설명' 블록의 5째 줄)

해당 옵션을 지정하더라도 블록되지 않을 수 있다.
==>
해당 옵션을 지정하더라도 블록 될 수 있다.

2006-10-251
4105

((p 105) 예제 4-1)

소스 코드에서

#define MODULE을 삭제

2007-01-204
111

((p.111) 밑에서 네번째 줄)

modeprobe 프로그램은
==>
modprobe 프로그램은

2006-10-251
119

((p.119) 밑에서 다섯번째 줄)

숨표(,)로 구분된다.
==>
쉼표(,)로 구분된다

2006-10-251
120

((p.120) [예제 4-8] 소스)

03  #include <linux/kernel.h>04
05  static int onevalue = 1;
==>
03  #include <linux/kernel.h>
04
05  static int onevalue = 1;

2006-10-251
120

(p120, p122 예제 제목)

[예제 4-8] 커널 2.4 모듈 매개변수 예제(2.6/praram/test.c)
->[예제 4-8] 커널 2.4 모듈 매개변수 예제(2.4/praram/test.c)

[예제 4-9] 커널 2.4 모듈 매개변수 예제(2.6/praram/test.c)
->[예제 4-9] 커널 2.6 모듈 매개변수 예제(2.6/praram/test.c)
==>
확인중

2006-10-251
121

((p.121) 둘째줄)

I(i 대문자): int
==>
i(I 소문자): int

2006-10-251
123

((p.123) 박스 [변수 타입])

ushort: short
==>
ushort: unsigned short

2006-10-251
123

((p123) 실행방법밑으로 세번째 줄.)

[root@]# insmod test.o onevalue=0x27 twostring="oh my godrmmod test"
==>
여기서 test.o를 test.ko로 수정

2006-10-251
125

((p.125) 넷째줄)

printk("<6>" "vsystem ok
");
==>
printk("<6>" "system ok
");

2006-10-251
125

(p125 마지막 단락)

데이터가 소실된다.
==>
데이터가 손실된다.

2006-10-251
125

(p 125 마지막 단락)

등록되어 있는 (소실->손실) 정정 정보가 잘못되었다.
데이터가 사라지는 "소실"을 뜻하지 손해를 보는 "손실"의 의미가 아니다.
==>
확인중

2006-10-251
126

((p.126) 두번째 문단 셋째줄)

ALT+F1
==>
CTRL+ALT+F1

2006-10-251
130

((p 130) 모듈 적재 과정 (3))

모듈 적재 과정중 항목 (3)에서
4번째 줄

할당받은 메모리 영역 중 module 구조체의 내용을 초기하고 모듈명을 그 뒤에 복사한다.

초기하고 -> 초기화 하고
==>
확인중

2006-10-251
132

(p132 첫번째 단락)

디바이스 드라이버로 내부적으로 많은 데이터 구조를...
==>
디바이스 드라이버도 내부적으로 많은 데이터 구조를...

2006-10-251
132

(p132 첫번째 단락)

오류정정 정보로 올라와 있는 해당 문구가 해당 위치에 없습니다.
잘못된 정보입니다.
==>
확인중

2006-10-251
134

((p.134) 밑에서 7번째 줄)

문제가 발행할
==>
문제가 발생할

2006-10-251
136

((p 136) 구조체 소스)

구조체 예제에 
u8 data2 -> u8 data2; 
로 변경
==>
확인중

2006-10-251
137

((p137) 13번째 줄)

빅 엔디언 방식이면 __BIC_
==>
빅 엔디언 방식이면 __BIG_

2006-10-251
145

(예제 5-1 소스 15줄)

buff = kmalloc (1204, GFP_KERNEL);

부분에서 1204가 아니라 1024 인것 같습니다.

수정:
buff = kmalloc (1024, GFP_KERNEL);
==>
확인 중

2006-10-251
145

((p 145) 예제1의 get_free_pages_test 부분)

get_free_pages_test 부분이 컴파일은 되는데 포인터 관련 오류가 뜹니다.

__get_free_pages 함수에 맞게 작성된 예제가 아니라서 그런건데 본래 함수 선언에 맞게 고쳤습니다.

if에서는 간단히 커널 영역에서 메모리가 할당되므로 PAGE_OFFSET 이상의 영역에서 할당되었는지만 확인하게 했습니다.
==>
void get_free_pages_test(void)
{
  unsigned long page = 0ul;
  unsigned int order;

  order = get_order( 8192 * 10 );
  page = __get_free_pages( GFP_KERNEL, order );

  if( (page & PAGE_OFFSET) == PAGE_OFFSET )
  {
    sprintf( (char*)page, "__get_free_pages test ok [%d]
", order );
    printk( KERN_ALERT "%s
", page );
    printk( KERN_ALERT "Page address: %x
", page );
    free_pages( page, order );
  }
}

2006-10-251
146

(예제 5-1 소스 39 줄)

buff = vmalloc(33 * PAGE_SIZE);

에서 PAGE_SIZE max 값으로 할당을 하는것 같은데,
33 이 아니라 32가 아닐까요? ^^;

수정:
buff = vmalloc(32 * PAGE_SIZE);
==>
확인중

2006-10-251
149

((p.149) 실행 결과에 관한 의견)

의견) 책에 나온 실행 결과는 2.6 소스를 실행했을 때의 결과입니다.
커널 2.4와 2.6 소스가 서로 다르기 때문에 실행 결과도 다르게 나옵니다. 
처음 배우거나 익숙치 않은 독자들이 혼돈할 수 있으니 어떤 코드의 실행 결과인지 명시해 주는 것이 필요하다 생각됩니다.
==>
실행 결과 내용을 다음과 같이 수정/추가합니다.

[커널 2.4]
Module Memory Test
kmalloc test
Small Memory Ok
Big Memory Ok
vmalloc test
vmalloc test ok
get_free_pages test
__get_free_pages test ok[5]

[커널 2.6]
Module Memory Test
kmalloc test
test memory 
Big Memory Ok
vmalloc test
vmalloc test ok
get_free_pages test
__get_free_pages test ok[5]

2006-10-251
154

(p 154, 소스코드 51번줄)

printk("allocte fail
");
==>
printk("allocate fail
");

2006-10-251
166

(p166 밑에서 3번째줄)

호출되는 인터럽트 함수 함수도 중요하다.
==>
혹은 호출되는 인터럽트 함수도 중요하다.

2006-10-251
173

((p.173) [그림 6-10] 위의 제목)

ioctl() <--> xxx_ioctl()
==>
ioctl(): xxx_ioctl()

2006-10-251
173

(p173 마지막 단락)

xxx_llseeek() 함수의 반환값은..
==>
xxx_llseek() 함수의 반환값은..

2006-10-251
179

((p.179) [그림 6-11])

[그림 6-11]에서 (3)번이 없음

그림 맨 오른쪽 아래 module_exit 내의 함수: register_chdrv
==>
(4)~(8)  => (3)~(7)로 변경

그림 맨 오른쪽 아래 module_exit 내의 함수: unregister_chdrv로 수정되야함

2006-10-251
179

(p 179 두번째 문단 1, 6 줄)

register_chdrv()
==>
register_chrdrv()

2006-10-251
179

((p 179) 그림6-11, 본문 4줄, 9줄)

그림에서 module_init(xxx_init)의 unregister_chdrv()가 register_chdrv()가 되어야 할듯 합니다.

따라서 본문 4째줄 "xxx_init() 함수는 unregister_chdrv()함수"의 unregister_chdrv()가 register_chdrv()가 되어야 합니다.
그리고 9째줄도 역시 unregister_chdrv()가 register_chdrv()가 되어야 할것 같습니다.
==>
확인중

2006-10-251
189

((p.189) 소스 설명 8번의 6번째줄)

call_releioctl()
==>
call_release()

2006-10-251
201

((p.201) 5번째 줄)

int open(struct ......)
==>
int xxx_open(struct....)

2006-10-251
210

((p 210) 첮번째 문단 넷째줄(3판))

일치하는 영역이 있는가를 확인한다. "없다면" 0을 -> "있다면" 0을
==>
확인중

2006-10-251
210

((p 210) 첮번째 문단 넷째줄)

일치하는 영역이 있는가를 확인한다. "없다면" 0을, 그렇지 않으면 0보다 작은 값을 반환한다.

수정

일치하는 영역이 있는가를 확인한다. "있다면" 0을, 그렇지 않으면 0보다 작은 값을 반환한다.

없다면 -> 있다면
==>
확인중

2006-10-251
218

((p218) 밑에서 6번째)

ssize_t write(struct.... )
==>
ssize_t xxx_write(struct... )

2006-10-251
222

(p.222 본문 5째줄)

요구된 값과 항상 일치하지 않을 수 있다는...
==>
요구된 값과 일치하지 않을 수 있다는...

2006-10-251
224

((p.224) 밑에서 6번째 줄)

이 데이터는 하드웨어에서 전달될 데이터일 수도 있고,
==>
이 데이터는 하드에어에 전달될 데이터일 수도 있고,

2006-10-251
224

((p.224) 밑에서 네번째줄)

데이터는 응용 프로그램에서 ~
==>
데이터를 가져올 위치는 응용 프로그램에서~

2006-10-251
225

(p 225. 밑에서 10째줄)

데이터를 읽었을 때 반환값이 요구된 값과 항상 일치할 수 없다는 점에 주의해야 한다. ->
==>
데이터를 읽었을 때 반환값이 요구된 값과 일치하지 않을 수 있다는 점에 주의해야 한다.

2006-10-251
231

(p 231, 함수 원형 정의 부분)

void readsw(...)
void readsl(...)
void readsl(...)
==>
void readsb(...)
void readsw(...)
void readsl(...)

2006-10-251
232

(p232 2번째 단락에 6번째줄)

모드 프로세스가 동일한...
==>
모든 프로세스가 동일한..

2006-10-251
234

(p234 ~ p235)

--------------------
verify_area() 사용예
--------------------
        ...
ssize_t write (...)
        ...

--------------------
copy_from_user() 사용예
--------------------
        ...
ssize_t write (....)
        ...

--------------------
get_user() 사용예
--------------------
        ...
ssize_t write (....)
        ...

--------------------
put_user() 사용예
--------------------
        ...
ssize_t read (....)
        ...
==>
--------------------
verify_area() 사용예
--------------------
        ...
ssize_t xxx_write (...)
        ...

--------------------
copy_from_user() 사용예
--------------------
        ...
ssize_t xxx_write (....)
        ...

--------------------
get_user() 사용예
--------------------
        ...
ssize_t xxx_write (....)
        ...

--------------------
put_user() 사용예
--------------------
        ...
ssize_t xxx_read (....)
        ...

2006-10-251
249

((p.249) verify_area( ) 함수의 매개변수)

VERIFY_WRITE: 읽기 쓰기 공간에 대한 검사
==>
VERIFY_WRITE: 쓰기 공간에 대한 검사

2006-10-251
250

((p250) copy_from_user() 기능)

(p250) copy_from_user()
기능 : 사용자 메모리 블록 데이터를 사용자 메모리 블록 데이터에 써넣는다
==>
사용자 메모리 블록 데이터를 커널 메모리 블록 데이터에 써넣는다.

2006-10-251
261

(p 261 6번째 줄)

주 번호와 부 번호의 비트수를 8비트에서 20비트로 확장했다.
==>
주 번호는 8비트에서 12비트로, 부 번호는 8비트에서 20비트로 확장했다.

2006-10-251
267

(p 267 코드 32번째 줄)

get_user(status, (char *) buf);
==>
get_user(status, (char *)&buf[loop]);

2006-10-251
270

(p 270, 소스코드 31번째줄)

get_user(status, (char *) buf);
==>
get_user(status, (char *)&buf[loop]);

2006-10-251
274

((p.274) 소스해설 2번)

[minor_app.c] 19~20행
==>
[minor_app.c] 19~32행

2006-10-251
277

(p 277 여기서 잠깐 밑에서 네번째줄)

/proc/ksyms 파일은
==>
/proc/ksyms 파일은(2.6 버전에서는 /proc/kallsyms)

2006-10-251
299

((p.299) 밑에서 7번째 줄)

예를 들어, 읽기와 쓰기 각각의 명령에 다른 구분 번호를....
==>
예를 들어, 읽기와 쓰기 각각의 명령에 같은 구분 번호를...

2006-10-251
301

((p.301) 7번째 줄)

디바이스 드라이버에 데이터를 쓰기 위한 데이터 버퍼(구조체)의 주소를 지정한다.
==>
디바이스 드라이버에서 데이터를 읽기 위한 데이터 버퍼(구조체)의 주소를 지정한다.

2006-10-251
305

((p 305) 소스라인 078)

소스의 078f라인에 ")" 가 빠졌습니다.

오류:
copy_to_user ((void*) arg, (const void*) &ctrl_info, (unsigned long) size;

수정:
copy_to_user ((void*) arg, (const void*) &ctrl_info, (unsigned long) size);
==>
확인중

2006-10-251
312

((p.312) 소스해설 4번 두번째 줄)

_IOW 매크로는 생성되는 32비트 명령의 읽기/쓰기에 속성 필드에 읽기 속성인 _IOC_WRITE 값을 포함시킨다.
==>
_IOW 매크로는 생성되는 32비트 명령의 읽기 쓰기 속성 필드에 쓰기 속성인 _IOC_WRITE 값을 포함시킨다.

2006-10-251
312

((p.312) 소스해설 5번 두번째 줄)

_IOWR 매크로는 생성되는 32비트 명령의 읽기 쓰기에 속성 필드 읽기 속성인 _IOC_READ와 _IOC_WRITE 값을 모두 포함시킨다.
==>
_IOWR 매크로는 생성되는 32비트 명령의 읽기 쓰기 속성 필드에 읽기 속성인 _IOC_READ와 쓰기 속성인 _IOC_WRITE 값을 모두 포함시킨다.

2006-10-251
313

((p.313) 12번 7번째 줄)

사용자 메모리 공간에 읽어야 하므로
==>
사용자 메모리 공간으로부터 읽어와야 하므로

2006-10-251
314

((p.314) 첫째줄)

info 구조체 변수에 전달한...
==>
info 구조체 변수에 전달할...

2006-10-251
329

((p.329) [그림 11-2] 오른편 그림)

init_timer(&timer));
....
....
add_timer(&timer));
....
....
del_timer(&timer));
==>
init_timer(&timer);
....
....
add_timer(&timer);
....
....
del_timer(&timer);

2006-10-251
330

((p.330) 두번째 문단 6번째 줄)

다음은 커널 2.4와 커널 2.6에서 0.03초가 지난 후에...
==>
다음은 커널 2.4와 커널 2.6에서 0.3초가 지난 후에...

2006-10-251
331

((p.331) 13번째 줄)

init_timer(&timer));
==>
init_timer(&timer);

2006-10-251
349

(p 349 밑에서 13번째 줄을 시작으로하여, 12장 전체에 해당)

unsigned long frags, const
==>
unsigned long irqflags, const


*
frags를 flags나 irqflags로 쓰는 것이 인자의 의미에도 맞고
함수원형 정의 된 부분을 봐도 2.4 대에서는 irqflags로 되어 있음.
커널 2.6에서는 인자의 이름은 정의되지 않고, 인자의 타입만 정의되어 있지만, 의미상 flags가 맞음

2006-10-251
359

(p359 마자막줄~p360 첫문단)

p 359 마지막째줄
local_restore_flags(frags);
->local_irq_restore(frags); 로 수정되야&#46092;

p 360 첫문단
위 예문을 보면 local_irg_enable() 함수를 사용하지 않는데, 그 이유는 

{ local_save_flags() => local_irq_restore 로 수정 } 

함수에 의해 저장된 frags 변수에는 이미 인터럽트 허가 상태가 포함되어 있기 때문에이다. 그래서 굳이 local_irg_enable()함수를 사용하지 않아도 

{ local_restore_flags()=> local_irq_restore 로 수정 }
 
함수에 의해 

{ local_irg_disable() => local_irq_enable 로 수정 } 

함수를 호출한 효과가 발생한다.
==>
확인중

2006-10-251
384

(384 맨 아래 단락)

커널 2.6에서는 프로세스 하나에 할당되는 시간이 0.001초로 정해져 있다.
-> 커널 2.6에서는 프로세스 하나에 할당되는 시간이 보통의 경우는 100ms이고 프로세스의 특성(cpu bound, io bound)에 따라 변동이 일어납니다. 또한 HZ 값에 따라서도 위의 시간값을 유지시켜 주고 있습니다. 0.001초라는 것은 x86 계열에서 기본적인 HZ값을 나타냄(타이머 인터럽트 주기), 프로세스 하나에 할당되는 시간이라는 표현보다는 프로세서가 프로세스에 할당할 수 있는 시간의 기본 단위가 0.001초라고 하는 것이 매끄러울꺼 같습니다.

2.4에서는 0.01초로 정해져 있다
-> 2.4에서도 2.6과 비슷하게 처리됨

커널 2.6에서는 프로세스 하나에 할당되는 시간이 0.001초로 정해져 있다.
-> 이 부분 역시 애매함

커널 2.6에서는 선점형 특성과 스케줄의 효율적인 구조로 인해 0.001초의 수행 시간을 보장하기 때문에 사용자에게는 커널 2.4보다 좀 더 원활하게 수행되는 것처럼 느껴진다
-> 0.001초의 수행시간을 보장한다는 말이 좀 어색하고, 기본적인 시간 할당단위가 짧고, 선점형이기 때문에 좀 더 정확한 시간에 스케쥴링 될 수 있는 가능성이 훨씬 크다 정도가 맞을 것 같습니다.(선점형이더라도 완전 fully 선점은 아니라서 스케쥴링 될 수 없는 구간도 없지 않아서 가능성 측면에서 얘기하였습니다)
그리고 원활하게 수행되는 것 처럼 느껴진다는 것 보다 응답시간이 빠르다는 표현이 이해가 빠릅니다.

그러나 아무리 커널 2.6이 우수하다고 해도 동시에 1000개의 프로세스가 동작한다면 프로세스에 할당된 시간을 모두 소모하는데 1초가 걸리므로 한 번 수행됐던 프로세스가 다음 번에 수행되려면 1초를 기다려야 한다.
-> 기본적으로 2.6에서는 타이머 인터럽트가 올 때마다 스케쥴링을 하지 않으며, 프로세스가 자율적으로 CPU를 포기하지 않는 이상 10ms이상의 time slice를 할당받고 그리고 프로세스 마다 할당된 time slice를 모두 소모하는데 프로세스 개수 뿐 아니라 프로세스들에 할당된 시간값도 영향을 줌. 우선순위가 높은 프로세스는 자신의 timeslice를 다 사용하여 expired queue로 들어가지 않은 경우, 또 I/O 요청이나 sleep으로 인해 쉬고 있는 경우, 이 경우에 요건만 충족되면 언제든 다시 수행될 수 있으므로, 1초를 기다려야 하는 것은 아님.
==>
커널 2.6에서는 프로세스 하나에 할당되는 시간이 0.001초로 정해져 있다.
-> 커널 2.6에서는 프로세스 하나에 할당되는 시간이 보통의 경우는 100ms이고 프로세스의 특성(cpu bound, io bound)에 따라 변동이 일어납니다. 또한 HZ 값에 따라서도 위의 시간값을 유지시켜 주고 있습니다. 0.001초라는 것은 x86 계열에서 기본적인 HZ값을 나타냄(타이머 인터럽트 주기), 프로세스 하나에 할당되는 시간이라는 표현보다는 프로세서가 프로세스에 할당할 수 있는 시간의 기본 단위가 0.001초라고 하는 것이 매끄러울꺼 같습니다.

2.4에서는 0.01초로 정해져 있다
-> 2.4에서도 2.6과 비슷하게 처리됨

커널 2.6에서는 프로세스 하나에 할당되는 시간이 0.001초로 정해져 있다.
-> 이 부분 역시 애매함

커널 2.6에서는 선점형 특성과 스케줄의 효율적인 구조로 인해 0.001초의 수행 시간을 보장하기 때문에 사용자에게는 커널 2.4보다 좀 더 원활하게 수행되는 것처럼 느껴진다
-> 0.001초의 수행시간을 보장한다는 말이 좀 어색하고, 기본적인 시간 할당단위가 짧고, 선점형이기 때문에 좀 더 정확한 시간에 스케쥴링 될 수 있는 가능성이 훨씬 크다 정도가 맞을 것 같습니다.(선점형이더라도 완전 fully 선점은 아니라서 스케쥴링 될 수 없는 구간도 없지 않아서 가능성 측면에서 얘기하였습니다)
그리고 원활하게 수행되는 것 처럼 느껴진다는 것 보다 응답시간이 빠르다는 표현이 이해가 빠릅니다.

그러나 아무리 커널 2.6이 우수하다고 해도 동시에 1000개의 프로세스가 동작한다면 프로세스에 할당된 시간을 모두 소모하는데 1초가 걸리므로 한 번 수행됐던 프로세스가 다음 번에 수행되려면 1초를 기다려야 한다.
-> 기본적으로 2.6에서는 타이머 인터럽트가 올 때마다 스케쥴링을 하지 않으며, 프로세스가 자율적으로 CPU를 포기하지 않는 이상 10ms이상의 time slice를 할당받고 그리고 프로세스 마다 할당된 time slice를 모두 소모하는데 프로세스 개수 뿐 아니라 프로세스들에 할당된 시간값도 영향을 줌. 우선순위가 높은 프로세스는 자신의 timeslice를 다 사용하여 expired queue로 들어가지 않은 경우, 또 I/O 요청이나 sleep으로 인해 쉬고 있는 경우, 이 경우에 요건만 충족되면 언제든 다시 수행될 수 있으므로, 1초를 기다려야 하는 것은 아님.

2006-10-251
392

((p.392) 13번째 줄)

매크로를 사용한다. wake_up_interruptible()
==>
매크로를 사용한다. interruptible_sleep_on()

2006-10-251
414

(p414 입출력 다중화 소개하는 글에서...)

select()와 pol()에 대하여 소개한다.
==>
select()와 poll()에 대하여 소개한다.

2006-10-251
421

(p 421 소스코드 46번 줄)

retval = poll((struct pollfd *)&Events, 3, 5000); < 0)
==>
retval = poll((struct pollfd *)&Events, 3, 5000);

2006-10-251
7434

(소스 코드)

103         get_user(status, (char*)buf);
->
103         get_user(status, (char*)&buf[loop]);

2008-12-226
456

(p 456 세번째 문단 마지막줄)

리스크 포인터만을
==>
리스트 포인터만을

2006-10-251
456

(p 456 첫째줄)

의미는 q_timer 구조체에
==>
의미는 tq_timer 구조체에

2006-10-251
473

(p 473 밑에서 3번째줄, p474 그림)

p473

금속클립 각각을 13번핀과 25번 핀에 꽂는다.
 

p474 

그림에서 금속클립중 입력신호 클립 -> 13
==>
p473

금속클립 각각을 13번핀과 25번 핀에 꽂는다.
 

p474 

그림에서 금속클립중 입력신호 클립 -> 10

2006-10-251
476

(p. 476 (7)번 항목)

다시 태스크 큐를 등록한다
==>
다시 워크 큐를 등록한다

2006-10-251
476

(p 476, (6)번 항목)

함수가 호출되면 태스크 큐를 등록한다
==>
함수가 호출되면 워크 큐를 등록한다

2006-10-251
525

((p.525) 밑에서 두번째 줄)

응용 프로그램에서 요구한 크기가 반환 함수값보다 작고
==>
함수 반환값이 응용 프로그램에서 요구한 크기보다 작고

2006-10-251
534

((p534) 밑에서 8번째 줄)

이 함수들은 주소를 각각 대입한다.
==>
이 함수들의 주소를 각각 대입한다.

2006-10-251
536

((p.536) 18번 두번째줄)

page - uf로 처리된 크기를...
==>
buf - page로 처리된 크기를...

2006-10-251
538

(p 538 네번째 줄)

/proc/sumproc/val1
==>
/proc/sumproc/val2

2006-10-251
542

(p 542 반환값 항목)

create_proc_entry() 함수의 반환값 항목의 설명이 잘못되었습니다.
==>
create_proc_entry() 함수는 생성된 엔트리(proc_dir_entry 형)의 포인터를 리턴합니다.

2006-10-251
545

((p.545) 첫째줄)

각 프로세서별로 동작하는 주소...
==>
각 프로세스별로 동작하는 주소...

2006-10-251
548

((p.548) 두번째 문단 둘째줄)

pad_t 구조체인
==>
pgd_t 구조체인

2006-10-251
556

((p.556) 7번째 줄)

응용 프로그램에서 호출한 .... 전달된다. -> 전체 문장의 재구성이 필요합니다.
==>
응용 프로그램에서 호출한 mmap() 함수에 사용되는 대부분의 매개변수 값들은  vma 커널에 의해 vm_area_struct 구조체 형태로 가공되어 디바이스 드라이버에 전달된다.

2006-10-251
558

((p.558) 5번째 줄)

from에 전달된 물리 주소를 to에 전달된 가상 주소로...
==>
to에 전달된 물리주소를 from에 전달된 가상주소에...

2006-10-251
560

(p 560, 그림 18-9)

vma->start는 remap_page_range의 to
vma->vm_pgoff는 remap_page_range의 from
==>
vma->start는 remap_page_range의 from
vma->vm_pgoff는 remap_page_range의 to
로 화살표 방향 바꿈

2006-10-251
566

((p 566) 예제 소스 15줄 (3판))

asm/mm.h
- >  linux/mm.h
==>
확인중

2006-10-251
566

((p 566) 예제 소스 15줄 (3판))

#include <asm/mm.h>
-> #include <linux/mm.h>
==>
확인중

2006-10-251
566

(p566 예제소스 15번째줄)

#include<asm/mm.h> => <linux/mm.h>
==>
확인중

2006-10-251
587

(p 587 소스해설 3)

[mmapnopage_dev.c] 68~83행

->[mmapnopage_dev.c] 50~60행
==>
확인중

2006-10-251
615

((p615) 박스 위 넷째 줄)

~ 문제를 해결하려면 전역 변수를 사용해야만 한다.
==>
~ 문제를 해결하려면 지역 변수를 사용해야만 한다.

2006-10-251
615

(p615 소스 6째줄~8째줄)

interruptible_sleep_on(&WaitQueue_Read);
local_cnt += (xxx_cnt - old_cnt );

->
interruptible_sleep_on(&WaitQueue_Read);
xxx_cnt ++;        ///< 추가 되어야됨 >
local_cnt += (xxx_cnt - old_cnt );
==>
확인중

2006-10-251
618

(p 618, 15줄)

선점 특성이 금지되는 경우는 선점 카운터가 0보다 작거나 같을 때다.
==>
선점 특성이 금지되는 경우는 선점 카운터가 0보다 클 때이다.(0일 경우만 선점가능)

2006-10-251
636

(p 636, dep_mbool 항목 맨 아랫줄)

$CONFIG_
PACKET
==>
$CONFIG_PACKET

2006-10-251
654

(p654 예제2)

11째줄  static int test_init (void)
=>  static int __init test_init (void)

17째줄  static void test_exit (void)
=>  static void __exit test_exit (void)

36째줄 __initcall(init_module);
=>  __initcall(test_init);
==>
확인중

2006-10-251
676

(p676 부번호 부분)

2.6관련 부분에서 "블록디바이스의 특성 정의"와 "주번호와 부번호 및 디바이스명" 부분은 2.4와 동일한 방식으로 처리하라고 되어있으나 부번호에 관한 내용은 2.6에 관해 별도 기술이 필요하리라 생각됩니다. p676에는 minor_shift에 관한 내용이 나오나 2.6의 gendisk 구조체에는 이 항목이 없고 minors에 직접 개수를 써넣게 됩니다.
==>
확인중

2006-10-251
679

((p.679) 밑에서 11번째 줄)

open 필드에 선언된 블록 디바이스 드라이버를 위한 open() 함수는 블록 디바이스 드라이버가 마운트되었을 때 호출된다.
==>
open 필드에 선언된 블록 디바이스 드라이버를 위한 open() 함수는 블록 디바이스가 마운트되었을 때 호출된다.

2006-10-251
680

((p.680) 6번째 줄)

release() 함수는 블록 디바이스 드라이버가...
==>
release() 함수는 블록 디바이스가...

2006-10-251
682

((p.682) 중간 코드)

int spull_revalidate(kdev_t i_rdev)
==>
앞선 코드들과 일관성을 위해
int xxx_revalidate(kdev_t i_rdev)

2006-10-251
683

((p.683) 코드 다음 문단 세번째 줄)

request_queue_t 구조체의 q 매개변수는 의미가 없다.
==>
request_queue_t 구조체의 q 매개변수는 의미가 있다.

2006-10-251
688

((p.688) 밑에서 9번째 줄)

파티션 영역은 파티션 검출되면
==>
파티션 영역은 파티션이 검출되면

2006-10-251
688

((p.688) 중간 소스부분)

1) static int xxx_size[4*4];
2) for(...) xxx_size[lp*4]=4*1024;
==>
1) static int xxx_size[2];
2) for(...) xxx_size[lp*4]=4*1024;

2006-10-251
688

((p 688) blk_size 설명 소스 부분)

static int xxx_size[2];
==>
static int xxx_size[8];

(디바이스크기 + 파티션크기*3) * 2 -> 8칸의 배열이 필요함

그래야지만 밑에서..
for (lp = 0; ....) xxx_size[lp*4] = 4*1024 구문에서 인덱스 0과 4를 접근하는데 문제가 없다고 봅니다

2006-10-251
689

((p.689) gendisk 구조체 부분 첫째줄)

하드 디스크와 같은 블록 디바이스 드라이버에는...
==>
하드 디스크와 같은 블록 디바이스에는...

2006-10-251
690

((p.690) 위치는 내용에서 명시)

7번째 줄 : 블록 디바이스 디바이스 드라이버의...
9번째 줄 : /proc/partition
밑에서 두번째 줄 : xxx_partitions[2*16]....
==>
7번째 줄 : 블록 디바이스 드라이버의...
9번째 줄: /proc/partitions
밑에서 두번째 줄 : xxx_partitions[lp*16]...

2006-10-251
700

((p.700) 5번째 줄)

넘겨진 위치는 섹터 수이므로
==>
넘겨진 위치는 시작 섹터 번호이므로

2006-10-251
714

((p.714) 맨 밑줄)

반대로 하드디스크에 데이터를 써넣으려면 써넣은...
==>
반대로 하드디스크에 데이터를 써넣으려면 써넣을...

2006-10-251
723

((p.723) 두번째 문단 첫째줄)

커널 2.6에서는 커널 2.4와 bio 구조체를 사용해 처리한다.
==>
커널 2.6에서는 커널 2.4와 달리 bio 구조체를 사용해 처리한다.

2006-10-251
726

((p.726) 첫번째 문단 첫째줄과 두번째 문단 세번째 줄)

첫번째 문단 첫째줄: 커널의 내부 처리가 끝나고 실질적으로 블록 디바이스에 데이터를...
두번째 문단 세번째 줄: xxx_req->rq_disk->private_data: 블록 디바이스 디바이스 드라이버...
==>
->커널의 내부 처리가 끝나고 실질적으로 블록 디바이스의 데이터를...
->xxx_req->rq_disk->private_data: 블록 디바이스 드라이버...

2006-10-251
728

((p.728) 코드에서 세번째, 다섯번째 줄)

XXX_MAX_PARTITONS
==>
XXX_MAX_PARTITIONS

2006-10-251
742

(p742, 예제 소스 경로)

[예제 22-3] 커널 2.4 디바이스 드라이버(2.4/vhdd/vhdd.c)
==>
[예제 22-3] 커널 2.6 디바이스 드라이버(2.6/vhdd/vhdd.c)

2006-10-251
742

(p742 예제22-2 line 31)

EXPORT_SYMBOL_NOVERS --> EXPORT_SYMBOL

EXPORT_SYMBOL_NOVERS를 사용할 경우 insmod vhdd.ko 명령 시 export된 vdisk를 찾지 못함.
==>
확인중

2006-10-251
748

(p748 첫번째줄)

10 [vhdd.c] 50행 : 

=> 10 [vhdd.c] 150행 :
==>
확인중

2006-10-251
749

(p 749 25번 해설)

25 [vhdd.c] 51~60행 :

=> 25 [vhdd.c] 70~75행 :
==>
확인중

2006-10-251
750

(p750 3쨰줄 중간)

end_request(vhdd_req,0)

=>end_request(vhdd_req,1)
==>
확인중

2006-10-251
767

(p 767, 첫째줄)

네트워크 디바이스 드라이버가 동작하기 위해서는 하드웨어 제어 정보를 담고 있는 struct register_netdev() 함수를 이용해 net_device 형식의 구조체 변수를 커널에 등록해야 한다.
==>
네트워크 디바이스 드라이버가 동작하기 위해서는  register_netdev() 함수를 이용해 하드웨어 제어 정보를 담고 있는 struct net_device 형식의 구조체 변수를 커널에 등록해야 한다.

2006-10-251
770

(p770 밑에서 7번째줄)

xxx_devs = alloc_etherdev(sizeof(xxx_net_data_t));
->xxx_devs = alloc_etherdev(sizeof(struct xxx_net_data_t));
로 수정바람
==>
확인중

2006-10-251
770

(p770 예제 소스 4번째줄)

xxx_devs = alloc_etherdev(sizeof(xxx_net_data_t));
->xxx_devs = alloc_etherdev(sizeof(struct xxx_net_data_t));
로 수정바람
==>
확인중

2006-10-251
772

((p.772) 두번째 문단 첫째줄, 다섯번째 문단 첫째줄)

1) 이렇게 init() 함수가 선언된 상태라면 다음과 같은 형식으로 네트워크 디바이스를 등록해야 한다.
2) 이 함수는 register_netdev를 이용해 커널에 등록한 네트워크 디바이스 드라이버를...
==>
1) 이렇게 init() 함수가 선언된 상태라면 다음과 같은 형식으로 net_device 구조체 변수를 등록해야 한다.
2) 이 함수는 register_netdev를 이용해 커널에 등록한 네트워크 디바이스 드라이버 구조체 변수를...

2006-10-251
774

(p774 예제소스 16번째줄)

xxx_dev = alloc_netdev(sizeof(xxx_net_data_t), "xxx_net%d", 
->
xxx_dev = alloc_netdev(sizeof(struct xxx_net_data_t), "xxx_net%d",
로 수정바람
==>
확인중

2006-10-251
776

((p.776) 6번째 줄)

net_device 구조체에...
==>
net_device 구조체의

2006-10-251
795

(p 795, 5째줄)

ioctl(skfd, SIOCSIFFLAGS, &ifr);
==>
ioctl(fd, SIOCSIFFLAGS, &ifr);

2006-10-251
811

(p 811, 밑에서 7째줄)

수신되지 못한 상태인 ISQ_TX_COL_EVENT를
==>
수신되지 못한 상태인 ISQ_RX_MISS_EVENT를

2006-10-251
23811

(811 page 밑에서 7번째줄)

수신하지 못한 상태인 ISQ_TX_COL_EVENT를
-> 
수신하지 못한 상태인 ISQ_RX_MISS_EVENT를

2008-01-154
854

(p 854, 21째줄)

.read = xxx_write,
==>
.write = xxx_write,

2006-10-251
913

(p 913, 밑에서 7째줄)

는 크기는 16비트로 제한되어 있다.
==>
는 크기는 24비트로 제한되어 있다.

2006-10-251
916

(p 916, 11번째 줄)

request_dma(XXX_DMA_CHANNEL);
==>
free_dma(XXX_DMA_CHANNEL);

2006-10-251
917

(p 917, 15째줄)

void *cpu_addr dma_addr_t dma_handle);
==>
void *cpu_addr, dma_addr_t dma_handle);

2006-10-251
920

(p920 9째줄)

그리고 현재 전송중이면 0 이외의 값을,
전송이 끝났거나 대기중이라면 0 을 반환한다.

=> 전송중이 0?1?그외? 대기중이 0?1?그외?
==>
확인중

2006-10-251
1111

(인터럽터관련 예제 소스 전반적)

커널버전 2.4에서 헤더파일이 소스 전반적으로(인터럽터, 태스크큐챕터) 틀렸습니다.
#include<linux/interrupt.h>=>#include<linux/sched.h>
로 수정 바람
==>
확인이 늦어지고 있습니다. 확인후 바로 수정하겠습니다.
페이지 번호는 임의로 1111로 해놓았습니다.

담당: IT전문서팀 임성춘(seongchun@hanbitbook.co.kr)

2006-10-251
5114

(p514 소스해설 2.)

140~414행 : 
-> 140~144행
==>
확인 중

2006-10-251