                     Ŀ  α׷ ȳ 

Version 1.1.0, 1999 4 26. 

   : Ori Pomerantz 
     : äö(dataeng@chollian.net) 
 : 1999 8 16.

 å    Ʒ , ׸  GPL ϴ.  
å GPLϿ Ӱ   ֽϴ. ٸ  쳪   
ο ˷ֽø  ̸ ݿ ̸,  ȳ ϰ  ϴ
   Դϴ.
η C,D  å    ⿡  ʾҽϴ.
η E GPL âƴ  ״ ο߽ϴ.


 ̵   Ŀ ⿡  ̴. ̰ Ŀ    
 ˱ ϴ ׸  C   ϴ α׷ӿ  
. ̰ ߿     Բ, How-To  Ŵ  
.  ̵ Ŀ   κ ٷ , װͿ    
ʿ  ̴ --- ̷      Ʈ, Ⱓ 
ῡ ã   ̴.   å  㰡 ǾƷ Ӱ 
ϰ   ִ. īǶƮ   Ʒ  캸 ٶ.

⿡ ޵  ǰ Ī  ǰ  ν Ȯ ϱ  
,  ǥ   ڿ   .  ǰ  ȸ, 
ȸ翡  ǵ  ʴ´

Copyright(c) 1999 Ori Pomerantz 
Ori Pomerantz 
Apt. #1032 
2355 N Hwy 360 
Grand Prairie 
TX 75050 
USA 
Email: mpg@simple-tech.com 

 Ŀ  α׷ ȳ ̴.   Ʈ  G-
NU  ̼(Ver2) ̸ ,    ִ.  2  å η
E Ǿ ִ.  å  ְ   Ǳ⸦ ٶ, ׷  
 嵵  ̴; ǰ ִ ǰ    ̸, Ư 
 ϰ ٲ  ̴. ڴ  å   īǶƮ Ͽ
鿡, Ȥ  θ  Ϳ ⸦  ̴. ٽ ϸ, 
  å  ϰ    ִ. , , Ǵ  ߰ 
üμ  Ǵ Ϳ    㰡 ʿ .  , Ļ
  ׸   ȯ ݵ GNU  ̼Ͽ ϴٴ 
̸,  īǶƮ  Ǿ߸ Ѵ.   å ο  ÷
ϱ Ѵٸ, ο     ҽ ڵ Բ(L A T E X 
)    , Ori Pomerantz   ˸⸦ ٶ. ̷
 μ ο  ߰ ̸,  迡 ϰ  ϰ 
ȴ.  å  ϰ  ȹ̶, ణ α, οƼ, 
,   Ʈ ڴ ڿ ū 縦  ̴. ̷ 
  Ʈ   Ʈ ⿩ϴ  ش. ̳
Ȥ ּ ִٸ,  ּҷ ϱ ٶ.


 
 
0. Ұ
0.1  ̰ о ϴ°?
0.2 ü  
0.3 ȭ ͵
0.3.1   1.0.1 ȭ
0.3.2   1.1.0 ȭ
0.4  
0.4.1 1.0.1 
0.4.2 1.1.0 

1. Hello, world 
   hello.c  
1.1 Ŀ   Makefiles 
   Makefile 
1.2  
  start.c 
  stop.c 
  Makefile 

2.  ġ ϵ
  chardev.c 
2.1   ҽ 

3. /proc  ý  
  procfs.c 
 
4. Է  /proc ̿ 
  procfs.c

5. ġ  (IOCTL ٷ) 
  chardev.c 
  chardev.h 
  ioctl.c

6. ʱ ǵ    
  param.c 

7. ý ȣ 
  syscall.c 

8. Blocking Processes  
  sleep.c 

9. printk's ġ  
  printk.c 

10. ½ũ ٸ 
  sched.c 

11. ͷƮ ó 
11.1 ڱ Ű 
  intrpt.c 

12. Ī  ó  

13. ϱ  Ǽ  

A. 2.0 2.2.107 ȭ 

B. 𿡼 ߰    ִ°?

C. ǰ  

C.1 ǹ  

D.  ȣǸ ̷(θ ϸ)  

E. The GNU General Public License  

 0  

Ұ 

   Ŀ  ۼϱ⸦ Ѵ.  C ȴ,  α׷
 ۼϰ  ̴. ׸,     𿡼 Ͼ
 𿡼 ϳ  ϵ Ͱ Ͻý   ִ, Ʈ
ھ  ߻ϴ   ֱ⸦ Ѵ. , Ŭ(: ۼϴ)
  ȯѴ.  DOS(Ե,   ü ߵ Ѵ)Ͽ 
 丮   ִ ϵ ͸  ְ,  Ͽ 
   𸥴. :  ڵ  Ƽ Ǵ  2.0.35
 2.2.3 ۼǰ ˻Ǿ. κ 쿡,  2.0.x 2.2.x̶
 ٸ CPU ٸ Ŀο ־   ̳     
.   ܴ 11̸, ̰ x86   ϰ  
̴.


0.1  ̰ о ϴ°?
 
  Ŀ ⿡  ˱ ϴ   ̴.  κп Ŀ
ο   ణ ٷ ̳, ̰    ƴϴ.  
     Ǹ  Ŀο   ִ.    Ŀ 
 ۼϱ ϴ   ̳,  2.2 Ŀο   ʴ.
 ̷ , η A  캸 Ѵ.    ͵ 
ϱ  , κ ⺻  ϰ   ϱ
    ̴. 

Ŀ   α׷ ̰,  α׷ӵ    Ŀ 
 о Ѵٰ ϴ´. ̹ , ý ó Բ ϴ ġ 
߿   ȮѴ.  ο α׷   ,
̺귯 ڵ带 Բ  ʾ,  "hello, world"α׷ ۼ߾
. ̷  Ŀο    ʴ´.  

0.2 ü   

     ũ ִ  Ѵ.  ̷ ϴ  װ
  ̸, ׸ κ  ŵ  μ ̰ д 
 Ѵ.   ߿  ˱ Ѵٸ,   ϰ, 
ҽ ڵ常  ȴ. ߿ 뿡   ּ ޾ Ҵ.


0.3 ȭ ͵
 
0.3.1   1.0.1 ȭ 

1.                                        - 0.3 
2.   ̽ ȣ ã°?                - 2  
3. ڿ ̽ ϵ     - 2  
4. Ŀ   Makefiles - 1.1 
5. Ī  μ - 12   
6. ' ' - 13  

0.3.2   1.1.0 ȭ 

1. Ŀ  2.2 ,  . 
2.  Ŀ  ҽ ϵ -  2.1  
3. 2.0 2.2 ȭ -  η A. 
4.  ҽ Ͽ Ŀ  -  1.2   
5. rmmod ý ȣ ȥ    - 7  


0.4    

 ̵ п   Yoav Weiss 帮, Ⱓ   Ǽ
   鿡  Ѵ.   Ǽ 幰 ʰ Ǽ 
 ...
 å T E Xʰ ' ġ, ' β 鼭 (?), 
Matt Welsh  T E X ۾ ϷǾ. 
  Ǹ ǥϸ,  縸  ǻͿ پ ü
ߵ  ٸ   ƹ   ҽڵ带 򵵷 (¾ -- 
   ؾ : -GNU ҽ̱⿡) 鿡 Ѵ.

0.4.1  1.0.1  

 ڿ    ο ǿ 縦 帰. Ʒ 
 Ư  ־:

״ Frodo Looijaard ȣƮ   Ȱ 2.1.xĿο  
־. 
 Stephen Judd ö  ־.. 
 Magnus Ahltorp ڿ  ġ     Ǽ 
 ־. 

0.4.2  1.1.0  

ĳ  Emmanuel Papirakis, 2.2Ŀο    ־. 
״ Frodo Looijaard   Ŀ  ۼ  ˷ ־. 

,  ڽ Ƿ  Ǽ ִ, ׸    å 
ʿϰ ϰ  α  ޱ⸦ Ѵٸ ׷  ̴. 

 1  

Hello, world 

ó  α׷Ӱ ù ° α׷   ǻ ȭ鿡 
, װ 罿 ׸ ȿ 'Hello, world' ڿ ׸ ̾. 
θ α׷  'Salut, Mundi' α׷ Բ ۵Ǿ.  ̷
  ߷ȴ 鿡   Ͼ 𸣰ڴ. ̷  ߰
 ʴ    ʾ Ѵ. 

ϳ Ŀ   ΰ Լ ;  Ŀ ȿ Ե  init
 ȣǰ, ŵǱ  cleanup  ȣȴ. , init 
Ŀΰ Բ   ϱ  ó ϰ ڽ ڵ Բ Ŀ 
 ϳ ġѴ.(Ϲ ڵ ΰ ϰ  Լ ȣѴ
). cleanup init  ߴ   ǵ̰,׷ 
ϰ  ϰ ȴ. 

<hello.c> 
/*  
/* hello.c 
*  Copyright (C) 1998 by Ori Pomerantz 
* 
*  "Hello, world" - Ŀ  . 
*/ 

/* ʿ  ϵ */ 
/* Ŀ  ȿ ǥ  */ 
#include <linux/kernel.h>	/* Ŀ ۾ Ѵ */ 
#include <linux/module.h>   /* Ư, ϳ ⿡ */ 

/* CONFIG_MODVERSIONS ٷ*/ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/*  ʱȭ */ 
int init_module() 
{ 
    printk("Hello, world - this is the kernel speaking\n"); 
    
	/* 0 ƴ  ϸ, init_module  Ÿ Ŀ  
     ʴ´ */ 
    return 0; 
} 

/* Cleanup - init_module  ߴ  ǵ */ 
void cleanup_module() 
{ 
	printk("Short is the life of a kernel module\n"); 
} 

1.1 Ŀ   Makefiles  

Ŀ    , Ʈ  Ŀ  ÿ ũ 
̴.  ڸ,  -c ÷׿ Բ  Ǿ Ѵ. , 
 Ŀ  Ʒ ǵ ɹ Բ  Ǿ Ѵ.

*. KERNEL --- ̴  Ͽ  ڵ尡  μ ƴ, Ŀ 忡 
 ˸, 
                 
*. MODULE --- ̴  Ͽ Ŀ    ǵ ϵ Ѵ.

*. LINUX ---  ڸ, ̰ ʿ ʴ. ׷,   ü
󿡼 ϱ⿡  ɽ Ŀ  ۼϱ ϸ, ̰  
   ̴. ̴ ü  Ǻ   ̴. 

ٸ ɹ Ͻ ÷׿  Եǰų,  ̴. Ŀ  
 ϴ Ȯ Ѵٸ, /usr/include/linux/config.h 캸.
                  
*. SMP --- Ī  μ. ̴ Ŀ Ī  μ  
 ԵǾ Ѵ( ϳ CPU󿡼 ). Ī  μ
Ѵٸ, ٸ ׵ ʿϴ(12 캸).

*. CONFIG MODVERSIONS --- CONFIG MODVERSIONS ȰȭϷ, Ŀ Ͻÿ 
 ʿ䰡 , /usr/include/linux/modversions.h ؾ Ѵ. ̰ 
 ڵ ڽſ  ϷǴ  ϴ. 

Makefile 

# ⺻ Ŀ   Makefile  
CC=gcc 
MODCFLAGS := -Wall -MODULE -D__KERNEL__  -D_LINUX 
hello.o: hello.c /usr/include/linux/version.h 
$(CC) $(MODCFLAGS) -c hello.c 
echo insmod hello.o ̸ Ѵ. 
echo rmmod hello ̸ Ѵ. 
echo 
echo X  Ŀ α׷ ȥ . 
echo insmod rmmod X ۿ Ѵ. 

,  Ʈ su  ϸ Ҵ
(Ʈ    ʾҳ?)(*1) 
1 ************************************************************************
Ʈ   ʴ   ϰ ý ϰ ̴. 
  Ȱ  ,  ſ ̴. 
******************************************************************************
 
׷ ɽ αٰŸ insmod hello rmmod hello غ. ̸ ϴ 
, /proc/modules ο Ŀ ⿡  ǰ ϵ ̴.  ׷, 
 X ٱ insmod Ѿ ϴ ɱ? ̴ Ŀ ޽ ǥ  p-
rintk ̿ϱ ̴. X ̿  ,  ޽  ̿ϴ 
 ͹̳(ALT-F?  õ) ǥõǸ,   ְ ȴ. ݸ鿡, X ̿
,   ɼ Ѵ. xterm -C ܼ  , ùٸ ޽ ǥ
õ ̴. ׷ġ ʾҴٸ,  ͹̳ 7 ޽  ޵ȴ -- X 
  ڵ.
 Ŀ Ҿϴٸ X  ޽  ʿ䰡 ִ. X ٱ,
printk Ŀο ַܼ  ޽ Ѵ. ݸ鿡, X ȿ, printk
޽  μ(xterm -C) ޵ȴ. CPUð  μ ŵǸ, 
X μ ̸  ̴. ׷, X ̸ ϸ, װ ǥ
 ̴ --- ׷, Ҿ ý  Ŀ ϰ  ϴ 
,  ̳   ޽   ̴.    Ǿ 
 Ŀ ˰ Ǵ ̴.  
 
1.2 Ŀ    

 Ŀ    ҽ Ϸ  찡 . ̷ 쿡, Ʒ 
 ʿϴ. 

1.  ҽ  ȿ ׷ ϳ, #define __NO_VERSION__ Ѵ. ̰
 module.h kernel_version Ǹ ϱ⿡ ߿ϸ. ϵ  Ŀ
  Բϴ  μ ߿ϴ. __NO_VERSION__ Բ module.h 
 Ƿ version.h ʿϴٸ ̰ ԽŲ.  

3. Ʈ ڵ带 Ѵ. ϵ ϳ ȴ. 
x86Ͽ, ̴ ld -m elf i386 -r -o <name of module>.o <1st source file>.o <sec
ond sourcefile>.o ȴ.
  
⿡ ̷ Ŀ   ִ. 

<start.c> 

/* 
* start.c 
* Copyright (C) 1999 by Ori Pomerantz 
* 
* "Hello, world" - Ŀ  . 
*     ƾ Ѵ. 
*/
 
/* ʿ  ϵ */ 
/* Ŀ ȿ ǥ  */ 
#include <linux/kernel.h>	/* Ŀ ۾ Ѵ.*/ 
#include <linux/module.h>   /* Ư, ϳ ⿡ */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/*  ʱȭ */ 
int init_module() 
{ 
	printk("Hello, world - this is the kernel speaking\n"); 
   	
	/* 0 ƴ   ϸ, init_module  Ÿ Ŀ  
   	 ʴ´ */ 
   	return 0; 
} 

<stop.c> 

/* 
* stop.c 
* Copyright (C) 1999 by Ori Pomerantz 
* 
* "Hello, world" - Ŀ  .  
*     ƾ Ѵ. 
*/ 

/* ʿ  ϵ */ 
/* Ŀ  ȿ ǥ  */ 
#include <linux/kernel.h>   /* Ŀ ۾ Ѵ.*/ 
#define __NO_VERSION__      /* Ŀ   ƴϴ.*/ 
#include <linux/module.h>   /* Ư, ϳ ⿡ */ 
#include <linux/version.h>  /* __NO_VERSION__, module.h ؼ Ե 
                               ʾҴ. */
 
/* CONFIG_MODVERSIONS ٷ*/ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/*  - init_module  ߴ  ǵ */ 
void cleanup_module() 
{ 
	printk("Short is the life of a kernel module\n"); 
} 

<Makefile> 

#  Ŀ   Makefile  
CC=gcc 
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX 
hello.o: start.o stop.o 
ld -m elf_i386 -r -o hello.o start.o stop.o 
start.o: start.c /usr/include/linux/version.h 
$(CC) $(MODCFLAGS) -c start.c 
stop.o: stop.c /usr/include/linux/version.h 
$(CC) $(MODCFLAGS) -c stop.c 


 2  

 ġ ϵ 

,  츮  α׷ӵ̴. ׸ ƹ ϵ  ʴ Ŀ 
  ۼϴ  ˰ Ǿ. 츮 ڽſ ںν  Ӹ  
ĵ. ׷, ¾ ΰ ߸  .    
. 

Ŀ  μ ϴ    ִ. ϳ ġ  ̿
ϴ ̰, ٸ ϳ proc  ý ̿ϴ ̴. Ŀ ̿ϴ 
  ϵ ġ ϱ ؼ̱⿡, ġϰ Բ   
̴. ġ    Ŀ ȿ μ ġ ̹ 
 ϴ ̰, ׸ ׵ ؼ  ġ(, ͹̳ )
 .

̷  Ʒ  Ǿ ִ.

 ġ ̹,   ϵ  ϴ, ڽ  ȣ Ҵ
޴´.  ̹ ϰ  ȣ /proc/devices Ÿ. ġ ̹
  Ǵ   ġ  ȣ Ҵ޴´. /dev 丮 
ġ , ġ Ϸ ȣ, װ ý   ġǾ  ʴ
, Ư ϵ Ѵ. 
 , ls -l /dev/hd[ab]* غ, ýۿ   IDEϵ ũ
Ƽ    ̴. ΰ   ȣ 3  Ϳ ָ϶. ׷
,  ȣ ٸ ġ ڵ ϳκ ȴ. ̰ PC ϴ
 Ȯϴ. ٸ  ýۿ  ġ ؼ  𸣰ڴ. ý
 ġǾ , ġ  ΰ mknodɿ  . ׵ /dev 
丮 ġϴ   .  ؼ ġ   , 
 ó, Ŀ   ϴ  丮 ȿ װ ġѵ 
  ʴ´.  

ġ ũ   ·   ִ:  ġ  ġ.   ̴
 ġ  û  ۸ , ׷,  Ƿ õȴ
 ̴. ̰   ġ,  ָ  ִ ͵麸,  
 ִ ͵鿡   ͸ ų д 鿡 ߿ϴ. ٸ ̴ 
 ġ  Է¸ ޾Ƶ̰ ϵ   ϴ(ũ ġ 
̴), ݸ鿡  ġ ׳ ų Ǵ    ̿븸 
. κ ġ ۸ ¸ ʿ  ʱ   ġ̰, 
  ũμ  ʴ´. ls -l  ù ° ڸ Ȯμ 
ġ   ġ  ġ   ִ. 'b' ġ̸, 'c'
  ġ̴.   κ :  ϴ κа ġ̹
 κ. init_moduleԼ module_register_chrdev ȣϿ Ŀ ġ ̺
 ġ ̹ Ѵ. ̰  ġ   ȣ Ѵ. claenu-
p_module Լ ġ  Ѵ. ̷(ġ ϰ ) ̵  Լ
 Ϲ ̴.  Ŀ ο ڽ ʱȭ , μ
ó, ׷ ȣǾ, ý ȣ Ͽ μ , Ǵ ͷ
Ʈ Ͽ ϵ ġ , Ǵ Ŀ ٸ κп (ܼ  
Լ ȣ⿡ ), ٷ ʱȭǾ ȴ.  ڸ , Ŀο 
带 ߰ϸ,     óμ ۵   װ 
  ̴.  
 **************************************************************************
⼭  ġ  ġ ǹ̰  ư ִ. Ϲ  
ġ ̶ Ҹ  ũ (512, 1K Bytes, ġ ) 
 б Ⱑ . ݸ鿡,  ġ ϳ(̷    
ϴ), Ȥ      ũ (  ũⰡ Ǿ 
 ̴ ٲ  ִ) .
ġ  ϵũ, CDROMġ, ÷ ũ ַ 뷮 ͸ 
ٷ ġ̸,  ġ   Ʈ,  ̴.
*******************************************************************************

ġ ̹ 4 device_<action>Լμ ̷, ġ   ȣ
Բ   ۾ Ϸ   ȣȴ. Ŀ ׵ ȣ  ƴ
 ġ ϵ  ־, ̵ 4 Լ , file_operations 
ü, Fops,  ؼ̴. ⼭ ؾ  ٸ  Ʈ ϴ ó 
(Ʈ ƴ)Ŀ  (rmmoded)ϴ  㰡 ʴ´. ġ 
  Ŀ  ϸ,  Լ (read/write) ̿Ǵ 
 ޸ ȣ Ű ȴ.  쿡 ƹ ڵ尡  ʰ, ణ
   ޼  , ־  ٸ Ŀ   
Ҹ ̿ϰԵȴ. ̷      ȴ.    
, 𰡸 㰡ϰ   , Լ ۾ ϴ   
ڵ()  Ѵ. cleanup_module Բ ̰ voidԼ̱⿡ ϴ
. cleanup_module ȣڸ,   ȴ. ׷, ī-󸶳  Ŀ
   Ŀ  ̿ϴ -  ī.(/proc/modules 
 ) ȣȴ. 0 ƴ϶, rmmod  ̴.    ī
 mod_use_count ȿ ϴ.  (MOD_INC_USE_COUNT, MOD_DEC_USE_-
COUNT) ó  ũΰ ǵǾ , mod_use_count  ̿ϴ 
ٴ ̵ ϴ    濡   ִ. 

<chardev.c> 
/* 
* chardev.c 
* Copyright (C) 1998?999 by Ori Pomerantz 
* 
*  ġ (б ) 
*/ 
/* ʿ  ϵ */ 
/* Ŀ  ȿ ǥ  */ 
#include <linux/kernel.h>   /* Ŀ ۾ Ѵ.*/ 
#include <linux/module.h>	/* Ư, ϳ ⿡ */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/*  ġ  */ 
#include <linux/fs.h>       /*  ġ ǵ ⿡ */ 
#include <linux/wrapper.h>  /*  ƹ ϵ  ʴ´. ׷  
                               ȣȯ  */ 

/* 2.2.3 /usr/include/linux/version.h  Ѵ. ׷, 2.0.35 
ʿ ʴ. ʿϴٸ ߰Ѵ. */
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

/* Ǻ , LINUX_VERSION_CODE   ڵ̴ */ 
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) 
#include <asm/uaccess.h> /* for put_user */ 
#endif 

#define SUCCESS 0 
/* ġ  **************************** */ 
/*  ġ  ̸, /proc/devices Ÿ ̴ */ 
#define DEVICE_NAME "char_dev" 
/*  ġκ ִ ޽ ũ */ 
#define BUF_LEN 80 

/*  ġ   ΰ?  ġ   ϱ  ̿ȴ */ 
static int Device_Open = 0; 

/* û  ־ ̽ ޽ */ 
static char Message[BUF_LEN]; 

/* μ 󸶳  ޽ °?  ϴ /device_read  ũ
   ⺸ ޽ Ŭ  ϴ */ 
static char *Message_Ptr; 

/*  Լ ġ   õϴ   ȣǾ  */ 
static int device_open(struct inode *inode, 
struct file *file) 
{ 
	static int counter = 0; 
        
    #ifdef DEBUG 
    printk ("device_open(%p,%p)\n", inode, file); 
    #endif 
        
    /* ϳ  ġ  ġ  ϴ 쿡  ġ ȣ 
        δ*/ 
    printk("Device: %d.%d\n", inode->i_rdev >> 8, inode->i_rdev & 0xFF); 
        
    /* ÿ  μ   ʴ´ٸ.*/ 
    if (Device_Open)  return -EBUSY; 
        
    /* 
    ̰ ϳ μ, ⿡  ɽ ؾ Ѵ.

    μ 쿡,  ϳ μ Device_Open ˻ϰ, ٸ
	μ ٷ   Լ  ̴. ó μ CPU
	 ư , μ  ġ   ʾҴٰ ȮѴ.

    ׷,  μ Ŀ ؽƮȿ Ǵ  ġ ʵ
	 Ѵ.

    SMP 쿡, ٸ CPU ϴ  ˻  Ŀ ٷ Device_Open 
    ų ̴. ׷, 2.0 Ŀο ÿ Ŀ   ϳ 
    CPU  Ǳ⿡  ʴ´. ɻ   2.2 ̰
	 Ǿ , , SMP Բ ̷ ۾  SMP迡 
	Ǵ Ȯغ ߴ. 
    */
            
    Device_Open++; 
        
    /* ޽ ʱȭ */ 
    sprintf(Message, "If I told you once, I told you %d times ?%s", counter++, 
	        "Hello, world\n"); 
        
    /* 
    ⿡ sprintf   ְ 㰡Ǵ  ޽ ִ ̰ BUF_LEN
      ̴. Ư Ŀ 쿡 ־  ÷ο찡 Ͼ 
	 ؾ Ѵ 
    */

    Message_Ptr = Message; 
        
    /* 
      ī͸ Ű Ϳ   ִ   ŵ 
	´(⿡ Ǿ ,  rmmod 0 ƴϸ rmmod ùٸ 
	 Ѵ. 
    */
        
    MOD_INC_USE_COUNT; 
    return SUCCESS; 
} 

/*  Լ μ ġ    ȣȴ.  2.0.x  
 ʱ  ׻ ȴ.  2,2,x  н  ǵ 
- ׷ ̰   ʿ  */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
	static int device_release(struct inode *inode, struct file *file) 
#else 
    static void device_release(struct inode *inode, struct file *file) 
#endif 
{ 
    #ifdef DEBUG 
    printk("device_release(%p,%p)\n", inode, file); 
    #endif 

    /*  ȣ   */   
    Device_Open--; 

    /* 
    ī , ٽ ϸ   Ƚ,     .
    */      
    MOD_DEC_USE_COUNT; 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    return 0; 
    #endif 
} 

/*  Լ ̹  ġ Ͽ     ȣȴ. */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t device_read(struct file *file, 
                           char *buffer,   /* ͸ ä  */ 
                           size_t length,  /*   */ 
                           loff_t *offset) /* Ͽ ġ */ 
#else 
static int device_read(struct inode *inode, 
                       struct file *file, 
                       char *buffer, /* ͸ ä  */ 
                       int length)   /*  (̰ ʰؼ  !) */ 
#endif 
{ 
    /*  ۿ    */ 
    int bytes_read = 0; 

    /* ޽ ̶, 0  Ѵ(  Ÿ) */ 
    if (*Message_Ptr == 0)  return 0; 
        
    /*   ȿ   */ 
    while (length && *Message_Ptr) 
    { 
    	/* 
        ۴ Ŀ  ׸Ʈ ƴ   ׸Ʈ  ֱ 
		 ۾ Ҵ ʴ´. ſ, put_user ̿ؼ Ŀ  
		Ʈ   ׸Ʈ ؾ߸ Ѵ.
        */
        put_user(*(Message_Ptr++), buffer++); 
        length--; 
        bytes_read ++; 
    } 

    #ifdef DEBUG  
    printk ("Read %d bytes, %d left\n", bytes_read, length); 
    #endif 
        
    /* б Լ ۿ     Ѵ. */ 
    return bytes_read; 
} 

/*  Լ  ġ Ͽ ⸦ õ  ȣȴ -   ȿ 
     */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t device_write(struct file *file, 
                            const char *buffer,  /*  */ 
                            size_t length,       /*   */ 
                            loff_t *offset)      /* Ͽ  ġ */ 
#else 
static int device_write(struct inode *inode, 
                        struct file *file, 
                        const char *buffer, 
                        int length) 
#endif 
{ 
        return -EINVAL; 
} 

/*   */ 
/* ġ   ġ ȣ. ̰ ,  ο Ǳ⿡  
   (, ,  ȿ  ؽƮ    )̴. */
static int Major; 

/*  ü μ  ġ ΰ Ϸ   Լ ϱ
    ȣȴ.  ü ʹ ġ ̺ ǰ, init_module
       ʴ´. NULL   ǵ  Լ
    ̴. */
struct file_operations Fops = 
{ 
	NULL,            /* O */ 
    device_read, 
    device_write,    
    NULL,            /* 丮 б */ 
    NULL,            /*  */ 
    NULL,            /*   */ 
    NULL,            /* ޸  */ 
    device_open, 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    NULL,            /*  */ 
    #endif 
    device_release   /*  */ 
}; 

/*  ʱȭ -  ġ  */ 
int init_module() 
{ 
	/*  ġ ( õ ) */ 
    Major = module_register_chrdev(0, DEVICE_NAME, &Fops); 

    /*    Ÿ. */ 
    if (Major < 0) 
    { 
    	printk ("%s device failed with %d\n", 
    			"Sorry, registering the character", 
    			Major); 
    	return Major; 
    }
 
    printk ("%s The major device number is %d.\n", 
    		"Registeration is a success.", 
    		Major); 
    printk ("If you want to talk to the device driver,\n"); 
    printk ("you'll have to create a device file. \n"); 
    printk ("We suggest you use:\n"); 
    printk ("mknod <name> c %d <minor>\n", Major); 
    printk ("You can try different minor numbers %s", 
    		"and see what happens.\n"); 
           
    return 0; 
} 

/*  -  /proc    Ѵ.*/ 
void cleanup_module() 
{ 
	int ret; 

    /* ġ  */ 
    ret = module_unregister_chrdev(Major, DEVICE_NAME); 
        
    /*  , Ѵ. */ 
    if (ret < 0)  printk("Error in unregister_chrdev: %d\n", ret); 
} 

2.1  Ŀ  ҽ  

ý ȣ, μ Ŀΰ ֵ Ӽ, Ϲ  ϰ 
ȴ. ο ý ȣ ߰,   Ͱ ϰ 
. ̰  ȣȯ  ʿϴ --- ο Ŀ   μ 
Ű ʰ Ѵ. κ 쿡, ġ ϵ  ϰ ȴ. 
ݸ鿡, Ŀ   ̽    ȴ. 
 Ŀ   (¦ ȣ)  (Ȧ ) 
.   ο  ̵ ϰ, ؾ Ǽ 
  ۼȴ. , ̵ 鿡  ̽   Ե
(̰  å    ̸,  ̰ ʹ  ۾ 
   ). ݸ鿡,  ,     ұ
   ̽   ִ. 
 ̵   2.0.x 2.2,x Ŀ   Ѵ.    
 , Ŀ     䱸ȴ. ̷ Ͽ ũ LI-
NUX_VERSION_CODE ̿ȴ. Ŀ  a.b.c ,  ũ  2^16a+2^
8b+c  ̴.  Ŀ    , KERNEL_VERSION ũθ 
Ѵ. 2.0.35 ǵ ʾǷ, ʿ  ̸ Ѵ.

 3  

/proc  ý 

 Ŀ   μ鿡  ϴ ߰  ִ--
/proc  ý.  μ鿡    νϱ  Ǿ
,   Ŀο,   ǥϴ /proc/modules, ޸ ̿ 
¸ ǥϴ /proc/meminfo , ̿ȴ.  
/proc  ý ̿ϴ ̷  ġ̹ ̿ϴ  ſ
ϴ --- /proc   ʿ   Բ ü , ó Լ
   (츮 쿡 ̰  ̴, /proc Ͽ  
⸦ õ    ȣǾ ). init_module Ŀΰ Բ ü ϰ 
cleanup_module ̸  ̴. 
츮 proc_register_dynamic* ̿ϴ      ̸ 
ϱ  ʱ ̸, Ŀο  浹   Ѵ. 
  ý ޸(/prco ġϴ)ٴ ũ  ġϸ, ̷ 
 inodeȣ  index-node ġϴ  ũ ġ Ÿ.
inode Ͽ  ,    , ũ ġ Ÿ 
 Ǵ  ͸ ߰  ִ ġ  Ѵ.    
/proc ýۻ  ų    ȣ⵵   Ƿ, 
 MOD_INC_USE_COUNT MOD_DEC_USE_COUNT  ִ   , ׸
    ŵǾ,      ȴ.
 忡  ڼ     ̸, ׷   , 
/procϵ ̷    Ѵ.

1 *************************************************************************
2.0, 2.2  inode 0 ϸ ڵ Ϸȴ.
*******************************************************************************

<procfs.c> 
/* 
* procfs.c - /proc  ϱ  
* Copyright (C) 1998-1999 by Ori Pomerantz 
*/
/* ʿ  ϵ */ 
/* Ŀ  ȿ ǥ  */ 
#include <linux/kernel.h>   /* Ŀ ۾ Ѵ.*/ 
#include <linux/module.h>   /* Ư, ϳ ⿡ */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/* /proc  ý ̿ϱ⿡ ʿ */ 
#include <linux/proc_fs.h> 

/*  2.2.3 /usr/include/linux/version.h  ũ ϳ, 2.0.35
   ׷ ϴ. ׷ ʿϴٸ ̰ ߰Ѵ. */ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

/* proc  ý Ͽ   */ 
/*
ڵ
==================== 
1. ͸   , ̿ ̶ ϶. 
2. ڵ  . Ŀο  Ҵ ۸ ̿   ϴ.. 
3. Ͽ  ġ. 
4. ù °   ũ. 
5. Zero (Ŀ ̿ ?).

   
==================== 
ڽŸ ۸ ̿ ,  ׷ ϴ  Ѵ,  ° ڿ ġ
 ϰ ۿ ̿ ũ⸦  ޴´.
  0̸ ̹ ̻ ( )   Ѵ.  
  ̴.

  
==================== 
 д ͸δ  Լ Բ  ؾϴ ߰   ̴. 
׷ ڵ带 캸 Ϳ     ִ. get_info ʵ proc_dir_en-
try  ̿Ǿ 캽(ַ ڴ find grep  ̿Ѵ)
μ ̰ ϰ Ǿ, ׸ <Ŀ ҽ 丮> /fs/proc/array.c 
Ǵ  Ҵ. Ŀο  𸣴  ִٸ, ̷    
Ѵ.  Ŀ ҽκ  Ŀٶ     ִ - 
װ ̿϶.
*/ 

int procfile_read(char *buffer, char **buffer_location, off_t offset,
                  int buffer_length, int zero) 
{ 
	int len; /*  ̿  */ 

    /* ̰ ̸  Լ ص  ޸   ִ.*/ 
    static char my_buffer[80]; 
    static int count = 1; 
        
    /*
    ʿ  ΰ   ־, ׷ ڰ   䱸ϸ, 
      ׻ "ƴϿ"̴. 

    ̰ ̺귯 ǥ readԼ ý ȣ  Ŀ   ,
	  ̻  ų, ۰    read ý ȣ 
	⿡ ߿ϴ.
    */
    if (offset > 0)  return 0; 

    /* Fill the buffer and get its length */ 
    len = sprintf(my_buffer, 
                 "For the %d%s time, go away!\n",
                 count, 
                 (count % 100 > 10 && count % 100 < 14) ? "th" : 
                 (count % 10 == 1) ? "st" : 
                 (count % 10 == 2) ? "nd" : 
                 (count % 10 == 3) ? "rd" : "th" ); 
        
    count++; 

    /* ۰   ġϴ ˸. */ 
    *buffer_location = my_buffer; 

    /* ̸  Ѵ. */ 
    return len; 
} 

struct proc_dir_entry Our_Proc_File = 
{ 
	0,		/* Inode ȣ - , proc_register[_dynamic]  ä. */ 
    4,  	/*  ̸  */ 
    "test", /*  ̸ */ 
    S_IFREG | S_IRUGO, /*   - , ׷, ٸ ΰ   ִ 
	                       ȭ */   
    1,		/* ũ ( Ǿ  丮) */ 
    0, 0,   /*   uid  gid  - Ʈ ־ */ 
    80,     /* ls  Ÿ  ũ */ 
    NULL,   /* inode󿡼   Լ(ŷ,  )?
               ƹ ͵  ʴ´. */ 
    procfile_read,	/*    б Լ,  б⸦ õ  ȣ
	                   .*/ 
    NULL    /*  inode ϱ  ⿡ Լ . ۹̼, 
	            Բ Ѵ */ 
}; 

/*  ʱȭ - proc  */ 
int init_module() 
{ 
	/* proc_register[_dynamic] ̸ , ƴϸ . */ 
        
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) 
    /*  2.2, proc_register üȿ  0̸ ڵ  
       inode ȣ ҴϹǷ, proc_register_dynamic ̻ ʿ . */ 
    return proc_register(&proc_root, &Our_Proc_File); 
#else 
    return proc_register_dynamic(&proc_root, &Our_Proc_File); 
#endif 
    /* proc_root proc  ý(/proc)  Ʈ 丮. ϴ  
       ġ  ִ. */ 
} 

/*   - /proc  Ѵ. */ 
void cleanup_module() 
{ 
    proc_unregister(&proc_root, Our_Proc_File.low_ino); 
} 
 

 4   

Է  /proc ̿ 

 Ŀ κ      ˰ Ǿ. ġ ̹ 
ϰ mknod ̿Ͽ ġ   ϸ,  /proc 
 ͵ ϴ. ̰ Է¿ ̿  ش. ,  
   ٴ ̴. Ŀ ⿡ Է   ù °  /pr-
oc Ͽ   ؼ̴.  /proc  Ͻý ַ μ鿡
 Ȳ Ÿ  ̸, Է   Ư  . proc_dir-
_entry ü Է Լ ͸  ,  Լ ͸
Ѵ. ſ, /proc Ͽ  ؼ, ǥ Ͻý  ̿ ʿ
Ѵ.
 װ  ý   ǥ ̴.  Ͻý
 ۰ inode* óϱ  ڽŸ Լ , struct_inode
 struct_file ͸ Ͽ, ̵ ̷ Լ鿡 Ǵ Ư 
ü̴. 
1 *************************************************************************
  ̴     ڽŰ Բ ٷ ̰, inode 
Ͽ  ũ() ϴ ó, Ͽ    ٷٴ 
̴. 
*******************************************************************************
/proc, ο   , ̿    struct_inode 
ϰ ȴ. ̰ 츮 ̿ϴ ̸, struct_inode  Է° 
  ͸ ϴ struct_file  ͸ Ѵ.   
  б  ǥ Ģ Ŀο ٲٴ ̴. б 
 ⸦  ̿Ǹ, ݸ鿡  Լ б⸦  ̿ȴ. ̴ б, 
Ⱑ Է    Ǳ ̴ --- μ Ŀο 
  ϸ Ŀ װ  ʿ䰡 , ׸ μ Ŀο
 ԵǸ Ŀ Էó װ ޾Ƶδ. 

 Ѱ ̷ο  module_permission Լ̴.  Լ μ /proc
Ͽ   Ϸ   ȣǾ, װͿ   㰡 Ǵ 㸦 
Ѵ. ̰  ۰  ̿ uid ٰϸ( , 
ǰ ִ μ  ϴ ü ), ׷ ٸ ͵, ٸ 
  ϰ Բ  ϴ, ¥ ð, Ǵ ŵ  Է
 ͵鿡 ٰϱ⵵ Ѵ. 

put_user get_user    ޸(  , ٸ 
 ٸ ) ׸Ʈ Ǳ ̴. ̰ Ͱ ޸
  ġ  ,  ޸𸮻 ׸Ʈ  ġϰ, 
 ̿  ׸Ʈ  ʿ䰡 ִٴ ̴. Ŀ  ϳ ׸
Ʈ , μ鿡  ϳ Ҵȴ. μ Ϸ  , 
 ڽſ Ҵ ׸Ʈ  ̿  Ƿ, ׸Ʈ ؼ 
ʿ䰡 . Ŀ ⿡   ,  ýۿ  ڵ Ǵ
Ŀ ޸ ׸Ʈ ϱ Ѵ. ׷,  ǰ ִ μ Ŀ
 ̿ ʿ ޸  Ѱ , Ŀ Լ μ ׸Ʈ ȿ 
ġ ޸  ͸ Ѵ. put_user get_userũδ  ޸𸮿 
ϵ Ѵ.

<procfs.c> 

/* procfs.c - /procȿ Ǵ , Է,   㰡ȴ. */ 
/* Copyright (C) 1998-1999 by Ori Pomerantz */ 

/* ʿ  ϵ */ 
/* Ŀ  ȿ ǥ  */ 
#include <linux/kernel.h>   /* Ŀ ۾ Ѵ.*/ 
#include <linux/module.h>   /* Ư, ϳ ⿡ */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/* /proc  ý ̿ϱ⿡ ʿ */ 
#include <linux/proc_fs.h> 

/*  2.2.3 /usr/include/linux/version.h ũθ ϳ, 2.0.35
׷ ϴ. ׷ ʿϴٸ ̰ ߰Ѵ. */ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
#include <asm/uaccess.h> /* get_user put_user  */ 
#endif 

/*   Լ */ 
/* ⼭ ŵ  ޽ ϸ,   Է ó  ִ.*/ 
#define MESSAGE_LENGTH 80 

static char Message[MESSAGE_LENGTH]; 

/*   ü ̿ϹǷ, Ư proc      - ⿡ 
    ó, ǥ б Լ ̿ؾ Ѵ.*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t module_output(
	struct file *file,  /*  б */ 
    char *buf,          /*  ׸Ʈ ȿ ͸    */ 
    size_t len,     	/*   */ 
    loff_t *offset)   	/* Ͽ  ġ -  */ 
#else 
static int module_output( 
    struct inode *inode,/* inode б */ 
    struct file *file,  /*  б */ 
    char *buf,          /*  ׸Ʈ ȿ ͸    */  
    int len)            /*   */        
#endif 
{ 
    static int finished = 0; 
    int i; 
    char message[MESSAGE_LENGTH+30]; 

    /*  ̸ 0,  ̻    ʴ. ݸ鿡, μ
          ȿ б⸦ Ѵ.*/ 
    if (finished) 
    { 
        finished = 0; 
        return 0; 
    }
        
    /* put user Ŀ ޸ ׸Ʈ ȣ μ ׸Ʈ ڿ
        Ѵ. get_user ݴ ...*/ 
    sprintf(message, "Last input:%s", Message); 
    for(i=0; i<len && message[i]; i++) put_user(message[i], buf+i); 

    /* 
	   , ޽ ũⰡ Ʒ ̸ ٰ ȮѴ. ׷ , 
	    ̴.  Ȳ, ޽ ũⰡ  ̺ ۴ٸ, 
       ̸   ̰,  ȣ⿡ len+1 ũ ޽ Բ ۴
	   ä.
	*/
    finished = 1; 
        
    return i; /* "read",  ũ⸦  */ 
} 

/*  Լ ڰ /proc Ͽ   ڷκ Է Ѵ.*/ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t module_input( 
	struct file *file,	/*  ڽ */ 
    const char *buf,    /* Է  */ 
    size_t length,      /*   */ 
    loff_t *offset)   	/* ϼ ġ -  */ 
#else 
static int module_input( 
	struct inode *inode,/*  inode */ 
    struct file *file,  /*  ڽ */ 
    const char *buf,    /* Է  */ 
    int length)         /*   */ 
#endif 
{ 
    int i; 
        
    /* ޽ ȿ Է ֱ, module_output  ߿ ̿ȴ.*/ 
    for(i=0; i<MESSAGE_LENGTH-1 && i<length; i++) 
        
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    get_user(Message[i], buf+i); 
        
    /* 
	 2.2 get_user ǹ̴ Ǿ. ̻ ڸ  ʵ,
    ׷ ù ° ڿ  ϱ ϰ,  ڿ  ׸
	Ʈ ͸ Ѵ.

     2.2 get_user ̷   short Ǵ int б⸦ 
     Ѵٴ ̴. б   ¸ ƴ  sizeof ̿ؼ̸, 
     ڽ  ʿϴ. 
	*/    
#else 
    Message[i] = get_user(buf+i); 
#endif 

    Message[i] = '\0'; /* ǥ Ѵ, 0 ڿ   */ 
    
	/* ̿ Է ڵ   ʿ䰡 ִ */ 
    return i; 
} 

/* 
 Լ  㰡(0 ), ( 㰡 ʴµ  Ÿ 
  )Ѵ. 

Ʒ  ϳμ Ѵ:
0 - (  - ⼭ ǹϴ)
2 - (Ŀ ⿡ Է)
4 - б(Ŀ κ )

̰  ۹̼ ˻ϴ   Լ̴. ls -l   Ǿ ۹
ǵ   ̸, ̰ øǴ  ϴ.
*/
static int module_permission(struct inode *inode, int op) 
{ 
	/* ο ⿡ б⸦ 㰡ϰ, Ʈ(uid 0)Ը ⸦ 㰡Ѵ.*/ 
    if (op == 4 || (op == 2 && current->euid == 0)) 
    	return 0; 
        
    /*  ͵ ƴ϶,  ȴ. */
    return -EACCES; 
} 

/*   .. -  ̰Ϳ  ũ  ʾƵ ,  
ī͸  ʿ ִ.*/
int module_open(struct inode *inode, struct file *file) 
{ 
    MOD_INC_USE_COUNT; 
    return 0; 
} 

/*  . - ٽ   ī   ̰ ̷ο 
   ̴ */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    int module_close(struct inode *inode, struct file *file) 
#else 
    void module_close(struct inode *inode, struct file *file) 
#endif 
{ 
	MOD_DEC_USE_COUNT; 

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    return 0; /*  */ 
    #endif 
} 

/* /proc ϱ  ü,   Լ Ϳ Բ */  
 
/* proc   . Ͽ   Ϸ   ȣǴ  Լ
    Ͱ ġѴ.NULL ƹ ͵  ʴ´ٴ ǹ̴.*/ 
static struct file_operations File_Ops_4_Our_Proc_File = 
{ 
    NULL,           /* lseek */ 
    module_output,  /* Ϸκ "б" */ 
    module_input,   /* Ͽ "" */ 
    NULL,           /* readdir */ 
    NULL,           /* select */ 
    NULL,           /* ioctl */ 
    NULL,           /* mmap */ 
    module_open,    /*   . */ 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    NULL,           /* flush,  2.2 ߰ */ 
    #endif 
    module_close,   /*   ݾҴ. */ 
        
    /* Ÿ . (/usr/include/linux/fs.h ־  ͵).⿡  ͵ 
     ʾǷ, ý ⺻  Ѵ. н ̰ 0̴(
      ̰ NULL). */
}; 

/*
proc   inode . ̿ϱ ϴ     ü ġ
Ű,  Լ ۹̼  ̿Ѵ. ̰  inode ۾  ٸ 
 Լ   ִ.(̷  ״ ٷ ʴ, ʿġ ʴ  NU-
LL Ѵ) 
*/
static struct inode_operations Inode_Ops_4_Our_Proc_File = 
{ 
    &File_Ops_4_Our_Proc_File, 
    NULL,          /* (create) */ 
    NULL,          /* lookup */ 
    NULL,          /* (link) */ 
    NULL,          /*  (unlink) */ 
    NULL,          /* ɹ (symlink) */ 
    NULL,          /* 丮 (mkdir) */ 
    NULL,          /* 丮 (rmdir_ */ 
    NULL,          /*  (mknod) */ 
    NULL,          /* ̸ (rename) */ 
    NULL,          /* readlink */ 
    NULL,          /* follow_link */ 
    NULL,          /*  б(readpage) */ 
    NULL,          /*  (writepage) */ 
    NULL,          /* bmap */ 
	NULL,          /* (truncate) */ 
    module_permission /*  㰡  ˻ */ 
}; 

/* 丮  */ 
static struct proc_dir_entry Our_Proc_File = 
{ 
    0,	/* Inode ȣ - , proc_register[_dynamic]   ̴. */ 
    7,  /* ϸ  */ 
    "rw_test",	/*  ̸ */ 
    S_IFREG | S_IRUGO | S_IWUSR,/*   - , ׷, ׸ ο б
	                                  . ,  ʵ 
								     ̸, module_permission  
								   ̸ ̿Ѵ. ̰  ʵ带 ̿ϱ
								   , ⼭ ʿġ ʴ. */  
    1,		/* ũ ( Ǵ  丮) */ 
    0, 0,   /*  uid gid - Ʈ  ־. */ 
    80,     /* ls  Ÿ  ũ */ 
    &Inode_Ops_4_Our_Proc_File,	/* ʿϴٸ,   inode ü 
	                                Լ ʿϹǷ ⼭ ʿϴ.*/
    NULL	/*   б Լ. ʿ,  inode ü ϱ⿡*/ 
}; 

/*  ʱȭ  */ 
/*  ʱȭ - proc  */ 
int init_module() 
{ 
    /* proc_register[_dynamic] 0̸ , ƴϸ  */ 
        
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    /* 
	 2.2 proc_register ü   0̸,  inodeȣ 
    Ѵ. ׷ proc_register_dynamic ̻ ʿġ ʴ. 
	*/ 
    return proc_register(&proc_root, &Our_Proc_File); 
    #else 
    return proc_register_dynamic(&proc_root, &Our_Proc_File); 
    #endif 
} 

/*   - /proc    */ 
void cleanup_module() 
{ 
    proc_unregister(&proc_root, Our_Proc_File.low_ino); 
} 


 5  

ġ  (IOCTL ٷ) 

ġ ϵ  ġ Ÿ. κ  ġ Է  
 ̿ϸ, Ŀ  μ鿡 ġ ̹ ,  ϱ  
 . ̰ ¸  ġ  ⿡  ϷǸ, Ϲ 
Ͽ  Ͱ   ۾ Ѵ. Ʒ , ̰ device_write 
 ȴ. ׷, ̰͸δ  ʴ. 𵩿    Ʈ
 (   , CPU ־ װ   
𵩿  Ʈ ,  ʹ ư  ʾƵ ȴ). 
𵩿  (   ȭ  ͸  ͱ), ׸ 
κ д  (ɿ    ȭ   )
ġ  ̿ϴ ̴. ϴ,   Ʈ ϴ  ϴ,
  ͸ ۼ   żӵ   ,  ڷ 
. н   ioctl̶ Ҹ Ư Լ ؼ̴(input o-
utput control  ).  ġ ڽ ioctl  , ioctl б
(μ Ŀη   ),ioctl (*1)(μ  
ϱ )     Ȥ ƴ  ִ.
 1 ************************************************************************
  б  Ģ ٽ ٲٴ , ioctl б Ŀο 
 ̰  Ŀο  Ѵٴ ̴.
*******************************************************************************
ioctl Լ 3 ڿ Բ ȣǾ: Ϸ ġ   , 
ioctl ȣ, ׸ ϳ , ̰   ̶ ϱ  ĳƮ(
cast:ȭ ) ̿ϴ  ϴ.(*2)  
 2 ************************************************************************
̰ ϰ ڸ Ȯ ʴ.   ü   .
--- ׷, ü ͸    ִ.
*******************************************************************************
ioctl ȣ  ġ ȣ, ioctl , , ׸    ȯѴ.
ioctl ȣ  Ͽ ǵ  ϳ ũ ȣ(_IO, _IOR, _IOW, _IOWR 
-- ¿ )  .    ̿Ǵ ioctl(̷ ؾ
  ִ ioctl Լ   ִ) Ŀ (̰ ظ ϰ 
) ο  #inlcudeǾ ԵǾ Ѵ. Ʒ ,   char-
dev,h ioctl.c ̿ϴ α׷ Եȴ. ڽ Ŀ ⿡ ioctl ̿
 Ѵٸ, ̰    ioctl ̴, ̷ μ 㰡
   쿬 ioctl  , ߸  ˰  ̴. 
  ϸ, Ŀ ҽ `Documentation/ioctl- number.txt' ϶.

<chardev.c> 

/* 
* chardev.c 
* Է/  ġ  
*/

/* Copyright (C) 1998-9 by Ori Pomerantz */ 

/* ʿ  ϵ */ 
/* Ŀ  ȿ ǥ  */ 
#include <linux/kernel.h>   /* Ŀ ۾ Ѵ.*/ 
#include <linux/module.h>   /* Ư, ϳ ⿡ */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/*  ġ  */ 
/*  ġ ǵ ⿡ */ 
#include <linux/fs.h> 

/* wrapper.h 翡  ʴ. ׷,  ȣȯ  ߰Ѵ. */
#include <linux/wrapper.h> 

/* ڽ ioctl ȣ */ 
#include "chardev.h" 

/*  2.2.3 /usr/include/linux/version.h ũθ ϳ, 2.0.35
׷ ϴ. ׷ ʿϴٸ ̰ ߰Ѵ. */ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
#include <asm/uaccess.h> /* get_user put_user  */ 
#endif 

#define SUCCESS 0 

/* ġ  */ 
/* ġ  ̸, /proc/devices Ÿ ̴. */ 
#define DEVICE_NAME "char_dev" 

/* ġ  ޽ ִ  */ 
#define BUF_LEN 80 

/* ġ Ⱑ  -  ġ     */ 
static int Device_Open = 0; 

/* û  ־ ġ ޽ */ 
static char Message[BUF_LEN]; 

/*  ޽ 󸶳 ָ ִ° - device_read  ޽  ũ
⺸ Ŭ  ϴ.*/
static char *Message_Ptr; 

/* ġ     ȣȴ. */ 
static int device_open(struct inode *inode, struct file *file) 
{ 
	#ifdef DEBUG 
    printk ("device_open(%p)\n", file); 
    #endif 
        
    /* ÿ ΰ μ ȭ  ʴ´. */ 
    if (Device_Open) return -EBUSY; 

    /*
	̰ ϳ μٸ, ٸ ϳ μ ̰ ϱ  
    Device_Open ϰ Ǿ ϱ ,    ſ ؾ Ѵ
	        
    ׷, Ŀ ο, ؽƮ  ȯ ȴ.
        
    ̰ SMP迡   ġ    ´. SMP ؼ 
    ߿ ٷ ̴.
    */ 
        
    Device_Open++; 

    /* ޽ ʱȭ */ 
    Message_Ptr = Message; 
        
    MOD_INC_USE_COUNT; 
        
    return SUCCESS; 
} 

/*  Լ μ ġ    ȣȴ.    ⿡ 
  .  Ͼ , ׻ ġ ᰡϰ ؾѴ(2.0. 2.2
 ġ   Ұ  ִ). */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static int device_release(struct inode *inode, struct file *file) 
#else 
static void device_release(struct inode *inode,struct file *file) 
#endif 
{ 
	#ifdef DEBUG 
    printk ("device_release(%p,%p)\n", inode, file); 
    #endif 
        
    /*  ȣ  غ */ 
    Device_Open--; 
        
    MOD_DEC_USE_COUNT; 
        
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    return 0; 
    #endif 
}

/*  Լ μ ̹  ġ    ȣȴ.*/ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t device_read( 
    struct file *file, 
    char *buffer,   /* ͸ ϱ   */ 
    size_t length,	/*  ũ */ 
    loff_t *offset) /*   ġ */ 
#else 
static int device_read( 
    struct inode *inode, 
    struct file *file, 
    char *buffer,   /* ͸ ϱ   */ 
    int length)     /*  ũ( ũ⸦ ʰؼ  !) */ 
#endif 
{ 
	/*  ۿ    */ 
    int bytes_read = 0; 

    #ifdef DEBUG 
    printk("device_read(%p,%p,%d)\n", file, buffer, length); 
    #endif 
        
    /* ޽ ̶, 0 ( ̶ ǹ̷) */ 
    if (*Message_Ptr == 0)  return 0;
        
    /*  ۿ   */ 
    while (length && *Message_Ptr) 
    { 
    	/* ۴ Ŀ  ׸Ʈ ƴ   ׸Ʈ ġϹ
		   ,  Ҵ ̷ ʴ´. ſ, put_userԼμ Ŀ 
		    ׸Ʈ   ׸Ʈ ͸ Ѵ.*/
    	put_user(*(Message_Ptr++), buffer++); 
    	length --; 
    	bytes_read ++; 
    }
        
    #ifdef DEBUG 
    printk ("Read %d bytes, %d left\n", bytes_read, length); 
    #endif 
        
    /* б Լ  ۿ ϵ   ̴.*/
	return bytes_read; 
} 

/*  Լ ġ Ͽ   ȣȴ. */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t device_write(struct file *file, 
	const char *buffer, 
    size_t length, 
    loff_t *offset) 
#else 
static int device_write(struct inode *inode, 
    struct file *file, 
    const char *buffer, 
    int length) 
#endif 
{ 
    int i; 

    #ifdef DEBUG 
    printk ("device_write(%p,%s,%d)", file, buffer, length); 
    #endif 
    for(i=0; i<length && i<BUF_LEN; i++) 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    get_user(Message[i], buffer+i); 
    #else 
    Message[i] = get_user(buffer+i); 
    #endif 
        
    Message_Ptr = Message; 
        
    /* Է¿ ̿    */ 
    return i; 
} 

/*  Լ μ ġ ϻ ioctl۾   ȣȴ. ΰ 
 (߰Ͽ inode  ü,  ġ Լ ) Եȴ:
ȣ ioctl  ioctl  ־ .

ioctl  Ȥ б/( ȣ μ ϵȴ.)̸, ioctl ȣ
  Լ  Ѵ. 
*/
int device_ioctl(struct inode *inode, 
                 struct file *file, 
                 unsigned int ioctl_num,    /* ioctl ȣ */ 
                 unsigned long ioctl_param) /* ioctl  */ 
{ 
	int i; 
    char *temp; 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    char ch; 
    #endif 

    /*ioctl ȣ⿡ ؼ ü */ 
    switch (ioctl_num) 
    { 
    	case IOCTL_SET_MSG: 
         	/* ޽( )   , ׸ ġ  ޽  */ 
         	/* μ  ־ ioctl ڸ ´. */ 
         	temp = (char *) ioctl_param; 
                
            /* ޽ ̸ ã´. */ 
            #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
            get_user(ch, temp); 
            for (i=0; ch && i<BUF_LEN; i++, temp++) get_user(ch, temp); 
            #else 
            for (i=0; get_user(temp) && i<BUF_LEN; i++, temp++); 
            #endif 
                
            /*  ٽ ߸  -  device_write ȣ */ 
            #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
            device_write(file, (char *)ioctl_param, i, 0); 
            #else 
            device_write(inode, file, (char *)ioctl_param, i); 
            #endif 
            break; 
        case IOCTL_GET_MSG: 
            /* ȣ μ  ޽ ش  - ڴ ̴.⸦
			   ä. */ 
            #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
            i = device_read(file, (char *)ioctl_param, 99, 0); 
            #else 
            i = device_read(inode, file, (char *)ioctl_param, 99); 
            #endif 
            /*  -  ̰ 100 Ȯ϶.  ÷ο찡 
			   μ ھ  ߱Ѵ. 99 ڰ Ǳ⿡ NULL 
			    ڸ   ʿϴ.*/
            /*   0 ߰ϸ,  ᰡ  ̴. */
            put_user('\0', (char *) ioctl_param+i); 
            break; 
       case IOCTL_GET_NTH_BYTE: 
            /* ioctl Է(ioctl_param), ( Լ )   
               Ƿ */ 
            return Message[ioctl_param]; 
            break; 
   	} 
        
   	return SUCCESS; 
} 

/*   */
/*
 ü μ  ġ ΰ Ϸ   Լ ϱ 
 ȣȴ.  ü ʹ ġ ̺ ǰ, init_module 
   ʴ´. NULL   ǵ  Լ  ̴
*/
struct file_operations Fops = { 
   	NULL,			/* O(seek) */ 
   	device_read, 
   	device_write, 
	NULL,           /* 丮 б(readdir) */ 
    NULL,           /* select */ 
    device_ioctl,   /* ioctl */ 
    NULL,           /* mmap */ 
    device_open, 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    NULL,           /* flush */ 
    #endif 
    device_release  /*  */ 
}; 

/*  ʱȭ -  ġ  */ 
int init_module() 
{ 
	int ret_val; 
        
    /*  ġ  ( õ) */ 
    ret_val = module_register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops); 

    /*    Ÿ. */ 
    if (ret_val < 0) 
    { 
    	printk ("%s failed with %d\n", 
    	        "Sorry, registering the character device ", 
    	        ret_val); 
    	return ret_val; 
    } 

    printk ("%s The major device number is %d.\n", 
            "Registeration is a success", MAJOR_NUM); 
    printk ("If you want to talk to the device driver,\n"); 
    printk ("you'll have to create a device file. \n"); 
    printk ("We suggest you use:\n"); 
    printk ("mknod %s c %d 0\n", DEVICE_FILE_NAME,MAJOR_NUM); 
    printk ("The device file name is important, because\n"); 
    printk ("the ioctl program assumes that's the\n"); 
    printk ("file you'll use.\n"); 
        
    return 0; 
} 

/*  - /procκ     */ 
void cleanup_module() 
{ 
    int ret; 

    /* ġ   */ 
    ret = module_unregister_chrdev(MAJOR_NUM, DEVICE_NAME); 
        
    /* ̸, ǥѴ. */ 
    if (ret < 0) 
    	printk("Error in module_unregister_chrdev: %d\n", ret); 
} 

<chardev.h>

/* chardev.h - ioctl Ǹ   . 
* 
* Ŀ (chardev.c) ioctl ȣϴ μ(ioctl.c)  ٿ ˷ 
* ϹǷ  Ͽ ־ Ѵ. 
*/ 
#ifndef CHARDEV_H 
#define CHARDEV_H 
#include <linux/ioctl.h> 

/*  ġ ȣ. ioctl ̰  ʿ䰡 ֱ ,   ̻ ŷ
  . */ 
#define MAJOR_NUM 100 

/* ġ ̹ ޽  */ 
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *) 

/* _IOR  μ Ŀ   ϱ  ioctl  
*  ٴ ̴. 
* 
* ù ° ڵ, MAJOR_NUM, ̿ϴ  ġ ȣ̴. 
* 
*  ° ڴ  ̴. 
* (  ٸ ǹ̸ Բ ) 
* 
*  ° ڴ μ Ŀηκ  ϴ  ̴. 
*/ 

/* ġ ̹ ޽  */ 
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *) 
/*  IOCTL ġ ̹ ޽     ̿ȴ. ׷, 
   Էϱ  ޽ μ  Ҵ ۿ   ʿ䰡 
   ִ. */ 
 
/* ޽ n°   */ 
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int) 
/*  IOCTL /  ٿ ̿ȴ. ڷκ n° ϳ  
, Message[n] Ѵ. */ 

/* ġ  ̸ */ 
#define DEVICE_FILE_NAME "char_dev" 
#endif 


<ioctl.c> 

/* ioctl.c - Ŀ  ioctl ϱ  μ. 
* 
*  /  cat ̿ ̴. ׷,  ڽ μ 
*  䱸Ǿ, ioctl ʿϴ.
*/ 

/* Copyright (C) 1998 by Ori Pomerantz */ 
/* ġ ԰ݵ, ioctl ȣ  ġ ϵ   */ 
#include "chardev.h" 
#include <fcntl.h>       /*  */ 
#include <unistd.h>      /*  */ 
#include <sys/ioctl.h>   /* ioctl */ 

/* ioctl ȣ  Լ */ 
ioctl_set_msg(int file_desc, char *message) 
{ 
	int ret_val;
        
    ret_val = ioctl(file_desc, IOCTL_SET_MSG, message); 
    if (ret_val < 0) 
    { 
         printf ("ioctl_set_msg failed:%d\n", ret_val); 
         exit(-1); 
    } 
} 

ioctl_get_msg(int file_desc) 
{ 
	int ret_val; 
    char message[100]; 
        
    /* 
     - Ŀο  ũ ۸   ʾұ⿡ ϴ. ̰ 
	÷ο츦 ߱  ִ.   α׷,   ioctl ̿
	 - ϳ Ŀο  ũ⸦ ˸ ٸ ϳ  ۸ ̿Ѵ.
    */
    ret_val = ioctl(file_desc, IOCTL_GET_MSG, message); 
    if (ret_val < 0) 
    { 
    	printf ("ioctl_get_msg failed:%d\n", ret_val); 
    	exit(-1); 
    } 
        
    printf("get_msg message:%s\n", message); 
} 

ioctl_get_nth_byte(int file_desc) 
{ 
	int i; 
    char c; 

    printf("get_nth_byte message:"); 
    i = 0; 
    while (c != 0) 
    { 
    	c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++); 
        if (c < 0) 
        { 
            printf("ioctl_get_nth_byte failed at the %d'th byte:\n", i); 
            exit(-1); 
        } 
        putchar(c); 
    } 
        
    putchar('\n'); 
} 

/* Main - ioctl Լ ȣ */ 
main() 
{ 
	int file_desc, ret_val; 
        
    char *msg = "Message passed by ioctl\n"; 
    file_desc = open(DEVICE_FILE_NAME, 0); 
    if (file_desc < 0) 
    { 
    	printf ("Can't open device file: %s\n", DEVICE_FILE_NAME); 
        exit(-1); 
    } 

    ioctl_get_nth_byte(file_desc); 
    ioctl_get_msg(file_desc); 
    ioctl_set_msg(file_desc, msg); 
        
    close(file_desc); 
} 

 6  

ʱ   

  鿡, Ŀ  , /proc    ̸ Ǵ 
ġ   ġ ȣ ٷ ioctl ̸ ߴ. ̴ н 
  α׷   ڰ ȭ ϰ ϵ ϴ öп 
ȴ.  ڿ  ۾ ϱ  α׷ Ǵ Ŀο ˸ 
ʿϴ. Ŀ  쿡, argc argv ڸ  Ѵ---ſ, 
  ´. Ŀ  ȿ  ϴ  ϰ, insmod 
    ̴.  Ŀ ⿡,   Ѵ; str1 str2.
ʿ ϴ   Ŀ   ǰ, insmod str1=xxx str2=yyy 
Ѵ. init_module ȣǸ, str1 ڿ xxx str2 ڿ yyy ȴ.
 2.0 ̵ ڴ ƹ ˻絵(*1)  ʴ´. str1 str2 ù °
ڰ ̸ Ŀ ڿ Ͱ ƴ integer    
.  Ǵ Ȳ ̸ ˻ؾ Ѵ.   2.2 ũ MACRO-
_PARM insmod ڵ ̸   ˸  ̿ȴ.  , ̰
 ڷ  Ŀ  ڿ Բ ϴ ڿ  㰡ϴ 
 ذ  ִ. 

1 *************************************************************************
C ڵ尡 ڷ ƴ   ġ Ƿ, ̴ Ұ
. ̰   ʿ ̴.
*******************************************************************************
 
<param.c>
/*  
*  ġ ÿ  ڵ   
*/ 

/* Copyright (C) 1998-9 by Ori Pomerantz */ 

/* ʿ  ϵ */ 
/* Ŀ ⿡ ǥ  */ 
#include <linux/kernel.h> 	/* Ŀ ۾  */ 
#include <linux/module.h> 	/* Ư, ϳ  */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

#include <stdio.h> 			/* NULL ʿϴ */ 

/* 2.2.3 /usr/include/linux/version.h ̸  ũθ Ѵ. 
׷, 2.0.35   ʿ 쿡 ̰ ߰Ѵ.*/ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

/* Emmanuel Papirakis: 
* 
*  ̸ (2.2) ũη ٷ. 
* Ŀ ɹ ̸ ̰  ѹ Ǳ⿡ ũ Ȯ ʴ´. 
* 
* ⿡ ڸ ϱ , include/linux/modules.h(line 176) ǵ ũ
 ̿ؾ Ѵ.  ũδ ΰ ڸ Ѵ.  ̸ ڷ.  
  ǥ(")̴.  , "i" ڷ̰ "s" ڿ̴.
*/ 
char *str1, *str2; 

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
MODULE_PARM(str1, "s"); 
MODULE_PARM(str2, "s"); 
#endif 

/* ʱȭ  - ڵ  */ 
int init_module() 
{ 
	if (str1 == NULL || str2 == NULL) 
    { 
         printk("Next time, do insmod param str1=<something>"); 
         printk("str2=<something>\n"); 
    } 
    else 
         printk("Strings:%s and %s\n", str1, str2); 

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    printk("If you try to insmod this module twice,"); 
    printk("(without rmmod'ing\n"); 
    printk("it first), you might get the wrong"); 
    printk("error message:\n"); 
    printk("'symbol for parameters str1 not found'.\n"); 
    #endif 
        
    return 0; 
} 

/*  */ 
void cleanup_module() 
{ 
} 

 7  

ý ȣ  

 . ܿ /proc ϰ ġ ó   ˰ԵǾ.  Ŀ 
α׷ӷμ ϴ , ġ ̹ ۼ ,   ִ. ׷, 
 쿡  ؾ,   ý    
?.  

̰ Ŀ α׷ֿ 迡 óϴ κ̴. Ʒ ,  open 
 ȣ  ״. ̴  ϵ   ,  α׷ 
  ٴ ̸, ǻ͸ ˴ٿ ϰ ȴ. ᱹ  ġ 
 Ѵ. ƹ ϵ ջ    ̴.  ϵ  ʵ
 ϱ , insmod rmmod ϱ  sync ϴ .  
/proc ġ ϵ ϴ ؾ. ׵   ͵̴. Ŀ  
  μ,  μ鿡  ϳ ̿Ǵ, ý ȣ̴. 
μ Ŀηκ 񽺸 û ( , ο μ ,
  ޸ 䱸),   ̷  ̿ȴ. ۾ ߿ Ŀ  
ϱ ϸ, ̷ ϵ   ִ. ׸, α׷ Ǵ μ
   ˱ ϸ, strace <command> <arguments> ϶. 
Ϲ, μ Ŀο  ϵ Ǿִ. Ŀ ޸  
Ұϸ ĿԼ ȣ⵵ Ұϴ. CPU ϵ  ̷  
Ѵ(̰ 'ȣ ' ȣϴ ̴). ý ȣ ̷ Ϲ 
Ģ  ̴. Ϳ    ä μ ϰų
, Ư  Ŀγ ̹ ǵ ġ бϵ ϴ  ߻Ѵ.(
,  ġ  μ  д  ϸ, ׷,   Ұ
ϴ).  CPUϿ ̰ ͷƮ 0x80  ȴ. ϵ  ġ
  ѹ бϴ  ˸,  忡 ̻  ѵȴ. ׷
 ý Ŀο ٸ -- ׷  ϴ    ְ ȴ. Ŀο
 μ ġ бϴ  ý ȣμ ϴ. ý ȣ ȣ 
 ġ ˻ϰ, Ŀο μ  û 񽺰  ˸. 
, ȣ ĿԼ ּҸ ˱  ý ȣ ̺(sys_call_table) ˾
.  Լ ȣϰ,   ý ˻ , μ   
(Ǵ ٸ μ, μ ð Ǹ).  ڵ带 б Ѵٸ, 
ҽ arch/architecture/kernel/entry.S ENTRY(ý ȣ)  о 
.

ý ȣ ۾ Ϸ, Լ  ϴ  ʿϸ( ణ
 ڵ带 ߰ϰ.  Լ ȣ), sys_call_table  Լ 
 Ѵ. ߿ ų Ҿ ¿ ý ϱ  Ƿ
, cleanup_module  ̺ ġ ǵ  ſ ߿ϴ.  
 ڵ尡 ̷ Ŀ  ̴. 츮  ڸ ('spy')ϱ 
, ڰ    printk ޽ Ÿ Ѵ.  ϸ, ڽ
Լ Բ   ý ȣ ġϴ, our_sys_open ȣȴ.  Լ
  μ uid( id) ˻ϰ,   uid ġϸ, printk
 ȣϿ   ̸ ǥѴ. ׶, ̵.  Ű 
Բ  openԼ ȣϿ     ִ.   

init_module Լ sys_call_table  ġ ġǰ   
 ȴ. cleanup_module Լ    · ǵ. ̷
   ý ȣ ΰ Ŀ   ɼ  ϴ. 
  Ŀ  A B ٰ غ. A A_open B B_open ý 
ȣѴ. , A Ŀο ߰Ǿ, ý ȣ A_open ġϰ, ȣ 
Ϸ   sys_open ȣ ̴. , B Ŀο ߰ȴ. ý
ȣ⿡  B_open ġǰ, Ϸ , A_open,  ý ȣ 
  ̴. 

, B ù ° ŵǸ,   ̴ -- ̰ ܼ  ȣ
A_opený ȣ   ̴, ׷, A ŵǰ, B ŵǸ, ý
  Ų. A Ŵ  ý ȣ  ϰ, sys_open, 
 B о. ̶, B ŵǾ,  ȣ̶  , 
 ޸𸮿  ʴ, A_open, ý ȣϿ  Ѵ. 켱,  Ư
 ذϰ, ̻ ȭŰ ʱ  ý ȣ openԼ ϸ 
׸   ʾ(׷ B ŵǾ  ýȣ  ʾҴ)
  ˻縦 ؾ ̴. A ŵǾ , ̰ ý ȣ B_open 
Ǿ ׷ ̻ A_open Ű  ָ, ̰ ޸𸮷κ
 ŵǱ  sys_open    ʴ´. , B_open 
̻ ƹ ͵   A_open ȣϷ õϸ,  ý B 
 ̵  Ű ȴ.  

̷          ִ. ù °, sys_open
 ȣ    ϴ ̴. , sys_open /proc/ksyms
 Ŀ ý κ ƴϸ, ̰Ϳ   . ٸ ϳ  Ʈ
ѹ   ϴ     ī͸ ̿ϴ ̴. ̰
 ⿡ ϳ, ⼭ δ  ʴ --- ̰ ⼭ ̷
   ʴ ̴.

<syscall.c>
/* syscall.c 
* 
* ý ȣ "Ŀ"   
*/ 

/* Copyright (C) 1998 -  by Ori Pomerantz */ 
/* ʿ  ϵ */ 
/* Ŀ ⿡ ǥ  */ 
#include <linux/kernel.h> 	/* Ŀ ۾ Ѵ. */ 
#include <linux/module.h> 	/* Ư,  */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

#include <sys/syscall.h> 	/* ý ȣ  */ 

/* (μ) ü ,  ڰ   ʿ䰡 ִ  */ 
#include <linux/sched.h> 

/* 2.2.3 /usr/include/linux/version.h ̸  ũθ Ѵ. 
׷, 2.0.35   ʿ 쿡 ̰ ߰Ѵ.*/ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
#include <asm/uaccess.h> 
#endif 

/* ý ȣ ̺(Լ ̺), ̰ ܺν ϸ Ŀ ins-
mod   ̰ ä ̴. */
extern void *sys_call_table[]; 

/* ˾ƺ ϴ UID  -  κ ȴ. */ 
int uid; 

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
MODULE_PARM(uid, "i"); 
#endif 

/*  ý ȣ⿡  . ȣ  Լ(sys_open) ̰ 
ؾϴ    ý ȣ ġ 𸣱 ̴.  
 Լ ϱ  sys_open ٸ  ġ  ֱ , ̰
100%  ʴٴ Ϳ ϶ - ׸,  ŵ  ִ. 

 ٸ , sys_open  ϱ ̴. ̰  ̸,  
ο  ʴ´
*/
asmlinkage int (*original_call)(const char *, int, int); 

/*   , 2.2.3 current->uid   ID ƴ, 0 
. ̰    ߸  ã    ִ - 
 uid    ý ȣ ̿  , ̰ μ ϴ
̶  ˰ԵǾ.

 ٸ   , Ŀ ̷  ֱ  Ŀ  Ͽ.
*/
asmlinkage int (*getuid_call)(); 

/*  Լ sys_openԲ ġ ̴(Լ ý ȣ ȣϿ  ȣ
Ǿ). Ȯ Լ  ã ,   ڷ, fs/open ó 
 . 

̷δ, Ŀ    ִٴ ̴. , ý ȣ 
κ   ʴ´(   䱸ȴ. ý ȣ Ŀΰ 
  ϹǷ) 
*/
asmlinkage int our_sys_open(const char *filename, int flags, int mode) 
{ 
	int i = 0; 
    char ch; 
        
    /* ڰ  ˱ ϸ, ˻Ѵ.*/
    if (uid == getuid_call()) 
    { 
    	/* getuid_call getuid ý ȣ̸, ȣ ý ȣ ϴ 
            uid ش. */ 
        /* ϴٸ,  ǥѴ. */ 
        printk("Opened file by %d: ", uid); 
        do 
        { 
        	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
            get_user(ch, filename+i); 
            #else 
            ch = get_user(filename+i); 
            #endif 
        
            i++; 
            printk("%c", ch); 
        } 
        while (ch != 0); 
        
        printk("\n"); 
	} 

    /*  sys_open ȣ - ݸ鿡,    ִ ɷ Ұ ȴ.*/
    return original_call(filename, flags, mode); 
} 

/*  ʱȭ - ý ȣ ġ */ 
int init_module() 
{ 
	/*  -  ݺ ʾ. ׷  ؼ... */ 
    printk("I'm dangerous. I hope you did a "); 
    printk("sync before you insmod'ed me.\n"); 
    printk("My counterpart, cleanup_module(), is even"); 
    printk("more dangerous. If\n"); 
    printk("you value your file system, it will "); 
    printk("be \"sync; rmmod\" \n"); 
    printk("when you remove this module.\n"); 

    /* original_call  Լ ͸ ϰ, our_sys_open Բ ý
        ȣ ̺ ý ȣ ġѴ. */ 
    original_call = sys_call_table[__NR_open]; 
    sys_call_table[__NR_open] = our_sys_open; 
        
    /* ý ȣ foo  Լ ּҸ  , sys_call_table[__NR_foo]
     . */ 
    printk("Spying on UID:%d\n", uid); 
        
    /* getuid  ý ȣ  */ 
    getuid_call = sys_call_table[__NR_getuid]; 
    return 0; 
} 

/*  -  /proc    */ 
void cleanup_module() 
{ 
	/* ý ݹ  · ǵ. */ 
    if (sys_call_table[__NR_open] != our_sys_open) 
    { 
        printk("Somebody else also played with the "); 
        printk("open system call\n"); 
        printk("The system may be left in "); 
        printk("an unstable state.\n"); 
    } 
        
    sys_call_table[__NR_open] = original_call; 
} 

 8  

μ  (Blocking Processes) 

 ùٸ   ſ 䱸ϸ  ൿϰڴ°? ٸ  
 Ѵٸ,  ' ȵ, ٻڴ ̾. !'  ϸ ȴ. 
, Ŀ ⿡ ٸ μ (?)ϸ, ٸ  ؾ Ѵ.
    · μ   ϴ. ᱹ, μ
 Ŀο  ǰ,  ð( μ ϳ CPU󿡼 ÿ 
Ǵ ̴)  ̴.   

 Ŀ  ̰ ̴. (/proc/sleep ȣ) ÿ ϳ μ
 .  ̹ , Ŀ  module_interruptible_sleep-
_on(*1) ȣѴ.  Լ ½ũ(½ũ μ ý ȣ⿡  
  ִ Ŀ  ü̴)    TASK_INTERRUPTIBLE 
ϰ,  ε    ʵ WaitQ ߰ϰ, ½ũ
 ť Ϸ  ٸ.  
1 *************************************************************************
  ϴ    tail -f   ̴.. 
*******************************************************************************

μ ϰ Բ Ǹ, ½ũ Ǹ, ׸ module_close ȣ
.  Լ ť  μ  ȴ(̵    ϳ 
). ̷μ μ       ִ.  ð, 
췯  μ鿡  ð ϰ ٸ μ CPU   
. ᱹ, ť μ  ϳ 췯 CPU   Ѱش. ̰
 modulue_interruptible_sleep_on(*2) ȣ Ŀ ۵ȴ.  ٸ 
鿡    Ͽ ڽ  ˸,   
ְ ڽ  ư. ٸ μ CPU ð Ϻθ  , 
  캸 ٽ · ư.  
2 *************************************************************************
μ  Ŀ  ȿ ִ --- μ  , open ý ȣ 
Ǿ ý ȣ  ϵ ʾҴ. μ ȣ (open) 
ϵ ǻ̿  CPU ð κ ϴ  Ѵ.  
*******************************************************************************

  Ȱ ϱ , module_close Ͽ Ϸ μ 
  ʴ´.  ȣ, Ctrl-C(SIGINT) , μ (*3).
̷ 쿡, -EINTR ٷ  Ǳ Ѵ. ̰ ڵ鿡 ߿ϸ, 
,  ޱ  μ  ϴ 쿡. ߿ϰ ؾ 
 ϳ  ִ.  μ ¸  ʴ´. ̷ μ
    O_NONBLOCK ÷׸ ̿Ѵ. Ŀ ٸ   ۿ 
, Ʒ     , -EAGAIN  ڵ带  ̴. cat_n-
oblock α׷,  ҽ 丮 ִ, O_NONBLOCK    ְ
 ̴.   
3 *************************************************************************
̰  module_interruptible_sleep_on ̿Ѵ. ſ, module_sleep_on
̿  , Ctrl-C ϴ ſ ȭ ڿԴ ҿ .
*******************************************************************************

<sleep.c> 
/* sleep.c - /proc ,   μ ÿ  ϸ, ϳ
 θ  · . */

/* Copyright (C) 1998-9 by Ori Pomerantz */ 

/* ʿ  ϵ */ 
/* Ŀ ⿡ ǥ  */ 
#include <linux/kernel.h> 	/* Ŀ ۾ Ѵ. */ 
#include <linux/module.h> 	/* Ư,  */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/* proc fs ̿ϱ⿡ ʿ */ 
#include <linux/proc_fs.h> 

/* μ  ·  , ׸ ߿   */ 
#include <linux/sched.h> 
#include <linux/wrapper.h> 

/* 2.2.3 /usr/include/linux/version.h ̸  ũθ Ѵ. 
׷, 2.0.35   ʿ 쿡 ̰ ߰Ѵ.*/ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
#include <asm/uaccess.h> 	/* get_user put_user  */ 
#endif 

/*  Լ */ 
/* Է μ  ϱ ,  ޽ Ѵ.  */ 
#define MESSAGE_LENGTH 80 

static char Message[MESSAGE_LENGTH]; 


/* Ͽ  ü ̿ϹǷ, Ư proc ̿   -  Լ 
    ǥ б Լ ̿ؾ߸ Ѵ. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t module_output( 
	struct file *file, 	/*  б */ 
    char *buf,         	/* ͸  ( ׸Ʈ) */ 
    size_t len,        	/*   */ 
    loff_t *offset)   	/*   ġ -  */ 
#else 
static int module_output( 
	struct inode *inode,/* inode б */ 
    struct file *file,  /*  б */ 
    char *buf,          /* ͸  ( ׸Ʈ) */ 
    int len)        	/*   */ 
#endif 
{ 
    static int finished = 0; 
    int i; 
    char message[MESSAGE_LENGTH+30]; 
        
    /*  ̸ 0 Ѵ -  ġ  ̻   . */ 
    if (finished)
    { 
    	finished = 0; 
        return 0; 
    } 

    /* ̰   ٸ, Ŀ α׷    */ 
    sprintf(message, "Last input:%s\n", Message); 
    for(i=0; i<len && message[i]; i++)  put_user(message[i], buf+i); 
    finished = 1; 
        
    return i; /* "read"     */ 
} 

/* /proc Ͽ ڰ ϸ,  Լ ڷκ Է Ѵ.*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
static ssize_t module_input( 
	struct file *file,	/*  ڽ */ 
    const char *buf,    /* Է  */ 
    size_t length,      /*  ũ */ 
    loff_t *offset)     /*   ġ - */ 
#else 
    static int module_input( 
    struct inode *inode,/*  inode */ 
    struct file *file,  /*  ڽ */ 
    const char *buf,    /* Է  */ 
    int length)         /*  ũ */ 
#endif 
{ 
	int i; 

    /* module_output ߿  ϰ, ޽ ȿ Է ִ´. */
    for(i=0; i<MESSAGE_LENGTH-- && i<length; i++) 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    get_user(Message[i], buf+i); 
    #else 
    Message[i] = get_user(buf+i); 
    #endif 

    /* 츮 ϳ ǥ Ѵ. 0 ڿ Ṯ */ 
    Message[i] = '\0'; 

    /*  Է   ʿϴ. */ 
    return i; 
} 

/*       1 */ 
int Already_Open = 0; 

/*  ϱ ϴ μ ť */ 
static struct wait_queue *WaitQ = NULL; 

/* /proc    ȣ  */ 
static int module_open(struct inode *inode, struct file *file) 
{ 
    /*  ÷װ O_NONBLOCK ϸ, μ   ٸ
        ʴ´ٴ ǹ̴. ̷ ,  ̹  , -EAGAIN 
       и ǥϸ, "ٽ õؾ Ѵ" ǹ, ſ  ٸ 
	     Ѵ. */
    if ((file->f_flags & O_NONBLOCK) && Already_Open) 
    	return -EAGAIN; 

    /* Ŀ  ȿ μ   ̶, MOD_INC_USE_COUNT  ù
        ġ̸, Ŀ ŵ  ̴. */
    MOD_INC_USE_COUNT; 

    /*  ̹  ,   ٸ. */ 
    while (Already_Open) 
    { 
    	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
        int i, is_sig=0; 
        #endif 
                
        /*  Լ  μ ϱ , ý ȣ Ͽ, 
           ó, ߰ȴ.  Լ ȣ Ŀ  簳 ̰, 
		    wake_up(&WaitQ)Ǵ Ctrl-C  ñ׳ ŵ , μ
		    . */
        module_interruptible_sleep_on(&WaitQ); 

        /*  , ̹ ñ׳ Ͽ   ʾǷ, -EINTR
            Ѵ(ý ȣ ). ̰ μ鿡  Ǵ  
           㰡Ѵ. */
                
        /* 
        * Emmanuel Papirakis: 
        *
        * 2.2.* ణ  ־. ñ׳ ΰ (64Ʈ) 
        *  ΰ unsigned long 迭 ϴ üȿ ȴ. 2 
        * ˻縦 ⿡ ؾ Ѵ.
        * 
        * Ori Pomerantz: 
        * 
        *  64Ʈ  ū    ̰, , ̹ 16Ʈ
		* ũ  Բ ϴ     ̴.  ڵ
        * 𿡼  ϴ.
        */ 
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
        for(i=0; i<_NSIG_WORDS && !is_sig; i++) 
        {
            is_sig = current->signal.sig[i] & ~current->blocked.sig[i]; 
        }
                
        if (is_sig) 
        { 
            #else 
            if (current->signal & ~current->blocked) 
            { 
            #endif 
            /*
            μ ͷƮμ ǰ close Ǵ   
             ⿡ MOD_DEC_USE_COUNT ߰ϴ  ߿ϴ. ⿡ 
			 ī͸  ,   Եǰ 0 
			  ԵǾ,  μ  Ǹ, ÿ 
               ִ. 
            */
            MOD_DEC_USE_COUNT; 
                        
            return -EINTR; 
        } 
	} 

    /* ⿡ ٸ, Already_Open 0 ̴. */ 
    /*   */ 
    Already_Open = 1; 

    return 0; /*  㰡 */ 
} 

/* /proc  Ǿ  ȣǾ. */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
int module_close(struct inode *inode, struct file *file) 
#else 
void module_close(struct inode *inode, struct file *file) 
#endif 
{ 
	/* Already_Open 0 , WaitQ μ  ϳ Already_Open 
       1  ̰   ȴ. Already_Open 1    ٸ μ
	    · ȴ. */
    Already_Open = 0; 

    /* WaitQ  μ  Ǹ,    ٸ ־
       ,    ְԵȴ. */    
    module_wake_up(&WaitQ); 
    MOD_DEC_USE_COUNT; 

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    return 0; /*  */ 
    #endif 
} 

/*  Լ  㰡(0 ), ( 㰡 ʴµ  Ÿ 
  ) Ѵ. 

Ʒ   ϳμ Ѵ:
0 - (  - ⼭ ǹϴ)
2 - (Ŀ ⿡ Է)
4 - б(Ŀθκ )

̰  ۹̼ ˻ϴ  Լ̴. ls -l   Ǿ ۹̼
   ̸, ̰ øǴ  ϴ.
*/
static int module_permission(struct inode *inode, int op) 
{ 
	/* ο ⿡ б⸦ 㰡ϰ, Ʈ(uid 0)Ը ⸦ 㰡Ѵ.*/ 
    if (op == 4 || (op == 2 && current->euid == 0)) return 0; 

    /*  ͵ ƴ϶,  ȴ. */
    return -EACCES; 
} 

/* /proc ϱ  ü,   Լ Ϳ Բ */  
/* proc   . Ͽ   Ϸ   ȣǴ  Լ
 Ͱ ġѴ. NULL ƹ ͵  ʴ´ٴ ǹ̴.*/ 
static struct file_operations File_Ops_4_Our_Proc_File = 
{ 
	NULL,           /* lseek */ 
    module_output,  /* Ϸ  "б" */ 
    module_input,   /* Ͽ "" */ 
    NULL,           /* readdir */ 
    NULL,           /* select */ 
    NULL,           /* ioctl */ 
    NULL,           /* mmap */ 
    module_open,    /* /proc   ȣ */ 
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    NULL,           /* flush */ 
    #endif 
    module_close    /*    ȣ */ 
}; 

/* proc   inode . ̿ϱ ϴ     ü 
ġŰ,  Լ ۹̼  ̿Ѵ. ̰  inode ۾  ٸ
Ͽ Լ   ִ.(̷  ״ ٷ ʴ, ʿġ ʴ  
NULL Ѵ) */
static struct inode_operations Inode_Ops_4_Our_Proc_File = 
{ 
	&File_Ops_4_Our_Proc_File, 
    NULL, 			/* (create) */ 
    NULL, 			/* lookup */ 
    NULL, 			/* (link) */ 
    NULL, 			/*  (unlink) */ 
    NULL, 			/* ɹ (symlink) */ 
    NULL, 			/* 丮 (mkdir) */ 
    NULL, 			/* 丮 (rmdir) */ 
    NULL, 			/*  (mknod) */ 
    NULL, 			/* ̸ (rename) */ 
    NULL, 			/* readlink */ 
    NULL, 			/* follow_link */ 
    NULL, 			/*  б(readpage) */ 
    NULL, 			/*  (writepage) */ 
    NULL, 			/* bmap */ 
    NULL, 			/* (truncate) */ 
    module_permission /*  㰡  ˻ */ 
}; 

/* 丮  */ 
static struct proc_dir_entry Our_Proc_File = 
{ 
	0,		/* Inode ȣ - , proc_register[_dynamic]   ̴. */ 
    5,  	/* ϸ  */ 
    "sleep",/*  ̸ */ 
    S_IFREG | S_IRUGO | S_IWUSR, /*   - , ׷, ׸ ο б
	                                   . , ⼭  ʵ
									   ̸, module_permission
									 ̸ ̿Ѵ. ̰  ʵ带 ̿
									ϱ , ⼭ ʿġ ʴ. */  
    1,		/* ũ ( Ǵ  丮) */ 
    0, 0,  	/*  uid gid - Ʈ  ־. */ 
    80,		/* ls  Ÿ  ũ */ 
    &Inode_Ops_4_Our_Proc_File, /* ʿϴٸ,   inode ü 
	                                Լ ʿϹǷ ⼭ ʿϴ.*/
    NULL	/*   б Լ. ʿ,  inode ü ϱ⿡ 
	        */ 
}; 

/*  ʱȭ  */ 
/*  ʱȭ - proc  */ 
int init_module() 
{ 
	/* proc_register_dynamic success̸ , ƴϸ  */ 
        
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 
    return proc_register(&proc_root, &Our_Proc_File); 
    #else 
    return proc_register_dynamic(&proc_root, &Our_Proc_File); 
    #endif
        
    /* proc_root proc fs(/proc)  Ʈ 丮̴. ϴ   
       ġŲ. */
} 


/*  - /procκ   . μ  WaitQȿ ̶
 open Լ ο      ֱ⿡ .  10 忡
̷  ó   ̴. */
void cleanup_module() 
{ 
	proc_unregister(&proc_root, Our_Proc_File.low_ino); 
} 

 9   

printk ġ  

 ó( 1 ), X Ŀ  α׷ ȥϿ ۼ  
. Ŀ  ۼϴ  ̰ Ȯ  , δ  
 ޼  tty(*1)    ϱ  ̴. ̰
Ŀ   Ŀ  νϱ  ߿ϸ, ̰ ׵ ο 
  ִ.     tty ,  ½ũ tty ü
   ̿Ǵ ̴. , tty ڿ   ̿ϴ 
  Լ ͸ ã  tty ü  鿩ٺ ȴ.  
1 *************************************************************************
Teletype,  н ý ſ ̿Ǵ Ű-- ձ, 
 н α׷ ̿Ǵ ؽƮ Ʈ ߻ ǹ,  ͹̳,
X ȭ ġ xterm, Ʈ   telnet, Ÿ . 
*******************************************************************************

<printk.c>
/* printk.c -   tty, X ؼ, telnet, Ǵ ٸ , ؽƮ 
               ϱ. */  

/* Copyright (C) 1998 by Ori Pomerantz */ 

/* ʿ  ϵ */ 
/* Ŀ ⿡ ǥ  */ 
#include <linux/kernel.h>	/* Ŀο  ۾ Ѵ */ 
#include <linux/module.h>   /* Ư, ⿡ */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/* ⿡ ʿ  */ 
#include <linux/sched.h> 	/* For current */ 
#include <linux/tty.h>      /* tty   */ 

/*  ½ũ ̿Ǵ  tty ڿ ǥѴ. */ 
void print_string(char *str) 
{ 
	struct tty_struct *my_tty; 
        
    /*  ½ũ  tty */ 
    my_tty = current->tty; 

    /* my_tty NULL̸, Ʈ tty ٴ ǹ( ,  ̶).
        쿡, ƹ ͵   . */
    if (my_tty != NULL) 
    { 
	/* 
	my_tty->driver tty  Լ ü̸, ̵   ϳ(write) tty 
	ڿ µ ̿ȴ.  ޸ ׸Ʈ, Ŀ ޸ ׸Ʈ, ο
	 ڿ   ִ.
       
     Լ ù ° ڴ,   Լ Ȯ   tty ؼ
	̿Ǳ ,  tty̴.  ° ڴ Լ Ŀ ޸(0) Ǵ 
	 ޸(0 ƴ ) ڿ   Ѵ.  ° 
	 ڿ ̸,  ° ڴ ڿ ̴. 
    */
                
    (*(my_tty->driver).write)( 
    	my_tty,         /* tty ڽ */ 
        0,              /*   ڿ  ʴ´. */
        str,            /* ڿ */ 
        strlen(str));   /*  */ 
    /* 
	tty  ASCII ǥ ؼ()ϴ ϵ ġ̴. ASCII 
	, ο ٷ ̵ϱ   ڰ, CR & LF, ʿϴ. ݸ鿡, н
	 ASCII LF    ̿ȴ -  CR ̿  ⿡ \n ̿
	   LF Ŀ   Į ʿ ġϰ ȴ. 
    
    ̰ н 쿡 ؽƮ  ٸ ̴. CP/M ̰ Ļ
	Ǿ, MS-DOS ó, ASCII ǥ ϰ ؼǱ⿡, ο 
	LF CRΰ 䱸ȴ.  
    */
    (*(my_tty->driver).write)(my_tty, 0, "\015\012", 2); 
	} 
} 

/*  ʱȭ  */ 
/*  ʱȭ - /proc   */ 
int init_module() 
{ 
	print_string("Module Inserted"); 
    return 0; 
}

/*  - /proc   */ 
void cleanup_module() 
{ 
    print_string("Module Removed"); 
} 

 10   

½ũ ٸ  

ſ , housekeeping:' ذῡ   ʴ  ƾ' ½ũ 
 ð ϵ ؾ Ѵ. ½ũ μ  Ϸϰ Ϸ, ̰
crontab Ͽ ־ Ѵ. ½ũ Ŀ ⿡  Ϸϰ Ϸ,  
ɼ . ù ° ʿ  ý ݿ    crontab 
Ͽ μ ִ ̰,    ⿡ .  ̰  ȿ
̴, ׷ --- crontab ο μ ϰų,  ޸𸮿 ο 
 μ аų, ޸ 𿡼 Ŀ   ϴ 쿡
ϴ.
̷  ſ, Ÿ̸ ͷƮ ȣ⿡  Լ   ִ. ̰ ½ũ
  ̸, ü tq_struct  ,  ⿡ Լ ͸ 
ϰ ȴ. ̶, tq_timer  ȣǵ ½ũ ϻ ½ũ queue_ta-
sk ְԵǸ,   ½ũ  Ÿ̸ ͷƮ ȴ. Լ  
ǵ ؾ ϱ ,  Ÿ̸ ͷƮ ǵ ȣ 
 tq_timer ̰ ٽ ִ  ʿϴ. 
⼭ ؾ  ߿  ϳ ִ.  rmmod  ŵ , ù ° 
 ī͸ ˻Ѵ. ̰ 0̸, module_cleanup  ȣ ̴.
̶,  ޸𸮿   Լ Ѵ.    Ÿ̸ ½ũ  
  ̻   ̵ Լ  ϳ ͸ ϰԵǸ,  
̸  Ѵ. ߿ ̰  (ǻ , ΰ  ƴ, 
1/100   ̴), Ŀ Ÿ̸Ӹ  ½ũ ϻ ½ũ ȣ
Ϸ  ̴. ,  Լ  ̻  ʴ´. κ , ̰
  ʰ  ޸ ̸,  ޽   ̴. ׷, 
 ٸ ڵ尡  ޸ ġ ϸ, ſ ߸  Եȴ. 
, ½ũ κ ½ũ      ϴ. cle-
anup_module  ڵ Բ ϵ Ƿ(void Լ̴),  ذå 
  ϵ ʰ ϴ ̴. ſ, ̰  μ rmmod ֱ
 sleep_onǴ module_sleep_on(*1) ȣѴ. , ̰   
Ͽ Լ(rmmod) Ÿ̸ ͷƮ ȣ  ŵǵ Ѵ.  Ÿ̸ 
ͷƮ rmmod μ , ťȿ  ̻ Լ  ϰ 
⿡ ϰ ŵȴ.

1 *************************************************************************
 Ȱ Լ̴. 
*******************************************************************************

<sched.c> 

/* sched.c - Ÿ̸ ͷƮ 󿡼 ȣǾ Լ ٸ */ 

/* Copyright(C) 1998 by Ori Pomerantz */ 

/* ʿ  ϵ */ 
/* Ŀ ⿡ ǥ  */ 
#include <linux/kernel.h> 	/* Ŀ ۾ Ѵ */ 
#include <linux/module.h> 	/* Ư, ⿡ */ 

/* CONFIG_MODVERSIONS ٷ*/ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 

/* proc fs ̿Ǳ⿡ */ 
#include <linux/proc_fs.h> 

/*   ½ũ ⿡ */ 
#include <linux/tqueue.h> 

/*  ¿ ߿ 쵵 ϱ  ʿϴ */ 
#include <linux/sched.h> 

/* 2.2.3 /usr/include/linux/version.h ̸  ũθ Ѵ. 
׷, 2.0.35   ʿ 쿡 ̰ ߰Ѵ.*/ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

/* ȣ Ÿ̸ ͷƮ Ƚ */ 
static int TimerIntrpt = 0; 

/* cleanup  ̿ȴ. intrpt_routine task_queue ִ  ⿡
ŵǴ   */ 
static struct wait_queue *WaitQ = NULL; 
static void intrpt_routine(void *); 

/*  ½ũ  task_queue ü, tqueue.h  */ 
static struct tq_struct Task = { 
	NULL,  	/*   ׸ - queue_task   Ѵ. */ 
    0,    	/* task_queue  ƹ ͵ ߰ ʾҴ. */ 
    intrpt_routine, /*  Լ */ 
    NULL  	/* Լ  void*  */ 
}; 

/*  Լ Ÿ̸ ͷƮ ȣȴ. void* Ϳ  - ½ũ Լ
*    ̿Ǹ, Ź ٸ ڸ . */
static void intrpt_routine(void *irrelevant) 
{ 
	/* ī͸   */ 
    TimerIntrpt++; 

    /* ŵǱ ϸ */ 
    if (WaitQ != NULL) 
    	wake_up(&WaitQ); /*  cleanup_module  ϴ. */ 
    else 
    	queue_task(&Task, &tq_timer); /* task_queueȿ ٽ ִ´. */ 
} 

/* proc fs Ͽ   */ 
int procfile_read(char *buffer, char **buffer_location, off_t offset, 
                  int buffer_length, int zero) 
{ 
	int len; /*  ̿ ũ */ 

    /* ̰ ̸  Լ   ޸𸮿  ִ. */ 
    static char my_buffer[80]; 
    static int count = 1; 

    /*   ѹ ְԵǸ,  ̻  İ  
       ׻ ''̴. */
    if (offset > 0) return 0; 

    /*۸ ä  ũ⸦ ´. */ 
    len = sprintf(my_buffer, "Timer was called %d times so far\n", TimerIntrpt); 
    count++; 

    /* Լ ۸ 𿡼 ȣߴ ˷ش. */ 
    *buffer_location = my_buffer; 
        
    /* ũ⸦  */ 
    return len; 
} 

struct proc_dir_entry Our_Proc_File = 
{ 
	0,		/* Inode ȣ  - , proc_register_dynamic  ȴ. */ 
    5,  	/*  ̸  */ 
    "sched",/*  ̸ */ 
    S_IFREG | S_IRUGO,/*   - , ׷, ΰ    ִ  
	                      */ 
    1,      /* ũ ( Ǵ  丮) */ 
    0, 0,   /*  uid gid - Ʈ  ־. */ 
    80,     /* ls  ǥõǴ  ũ */ 
    NULL,	/* inode ٷ Լ(linking, removing, etc.)  ͵  
               ʴ´. */ 
    procfile_read,	/*    б Լ,  ̰    ȣ
	                   ȴ. */ 
    NULL  	/* ۹̼, ڵ,  inode ٲٱ  Լ ġѴ. */ 
}; 

/*  ʱȭ  - /proc Ͽ  */ 
int init_module() 
{ 
    /* tq_timer ½ũ ťȿ ½ũ ִ´.  Ÿ̸ ͷƮ  
    ̴. */
    queue_task(&Task, &tq_timer); 

    /* proc_register_dynamic ̸ , ƴϸ  */ 
    #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) 
    return proc_register(&proc_root, &Our_Proc_File); 
    #else 
    return proc_register_dynamic(&proc_root, &Our_Proc_File); 
    #endif 
} 

/*  */ 
void cleanup_module() 
{ 
	/* /proc ϱ */ 
    proc_unregister(&proc_root, Our_Proc_File.low_ino); 

    /* 
	intrpt_routine  ȣ  . intrpt_routine Ҵ ޸
	 ϰ ½ũ ۾ ϴ tq_timer ϱ  ʿϴ.
	⿡ ñ׳ 㰡  ϶. 
    WaitQ NULL ƴϹǷ, ڵ ͷƮ ƾ  ð ˸.
    */
    sleep_on(&WaitQ); 
} 

 11 

ͷƮ ó 

 ϰ, Ŀγ μ û   ó  θ 
, Ư  ٷ, ioctl , ý ȣ . ׷, Ŀ 
 μ û  丸 δ ƴϴ. ٸ ۾, ̰ ſ 
ϴ, ǻͿ ϵ ġ ϴ ̴. 
CPU ǻ  ϵ ȣ ۿ뿡   ° ִ.  ù 
° ´ CPU ϵ   ,ϵ CPU   ʿ䰡 
 ̴.  ° ͷƮ ȣ, CPU ƴ ϵ  ϰ ޵Ǿ
ϱ⿡ ϵ ϰ ȴ.  ϵ ġ ſ   
޸𸮸 ,       Ҿ ȴ. 
, ϵ ͷƮ IRQ(Iinterrupt Request )(*1) Ҹ. 
  , ª(short) ׸ (long), ͷƮ ִ.  ª IRQ ſ 
ª Ⱓ ð Ǿ ϸ,  ð ǻʹ ǰ ٸ 
Ʈ  ʴ´.  IRQ    ð , Ǵ  ٸ 
Ʈ ߻  ִ( ġ ƴ).  ͷƮ ϴٸ,  
· Ǵ  . 
CPU ͷƮ ϸ,  ϰ ϴ ߰( ߿ ͷƮ 
,   ͷƮ ϷǸ ̰ óȴ), û ڵ ϰ
ͷƮ ó⸦ ȣѴ. ̴ ý Ҿ ¿  ʰ ߿ 
 ÿ ǽŰ ͷƮ ó⿡ 㰡 ʴ´ٴ ǹ̴. ͷƮ
ó⿡ ̷  ذå ʿ ,  ϵκ аų 
ϵ 𰡸 , ׸ ߿ ο  ó  (̰
 'bottom half' Ҹ),  ϰ ϴ ̴. Ŀ  
'bottom half' ȣ Ѵ --- ̰ Ǹ,   Ŀ  ȿ 
㰡   㰡Ǿ .    
̷  ϴ  õ IRQ ŵǾ  ȣ ͷƮ ó⸦ 
  request_irq ȣϴ ̴(  ̰ 16 ϳ̴).
 Լ IRQ ȣ, Լ ̸, ÷, /proc/interrupts  ̸ ͷƮ
ó⿡ ޵ ڸ Ѵ.  ÷״ IRQ ϰ ϴ ٸ ͷ
Ʈ ǥϱ  SH_SHIRQ   ְ SA_INTERRUPT ̰  ͷƮ
 ǥѴ.  Լ  IRQ óⰡ      㰡
   ̴. 
׸ , ͷƮ ó ȿ, ϵ ϰ ǰ 'bottom half'
ϱ  queue_task_irq tq_immediate mark_bh(BH_IMMEDATE) ̿ϰ
ȴ.  2.0 ǥ queue_task ̿    ͷƮ  
queue_task(*2) ߰ ߻  ־̴. ʱ    
32 'bottom half'迭 Ƿ mark_bh ʿϰ ׵  ϳ(BH_IMME-
DATE) 'bottom-half'   ġ  'bottom half'  Ʈ
̿ȴ.

1 ************************************************************************
̰   ǥ ̴. 
******************************************************************************

2 ************************************************************************
queue_task_irq   ݿ  ̰κ ȣȴ. --- 2.2   
queue_task_irq  queue_task ݿ  ȣȴ. 
******************************************************************************

11.1   Ű  

:   κ    ̴.   ϴ 
 ƴ϶, ùٸ   ̴.  ڵ带  Ϸ õ
.   

   ڵ   ִ.  ̰   ǹ 
  ִ ̴. ٸ , Ŀ ̹  ġ鿡  
̹  ϰ ְ, ̷ ġ ̹  ۼ Ͱ  
Ҽ . Ű ͷƮ   ڵ带  ذå  ߰ , 
  Ű ͷƮ Ҵ ϴ ̴. Ŀ ҽ Ͽ  ɹ
ǵǾ Ƿ(driver/char/keyboards.c), ̰    .  
带 insmodϱ  ٸ ͹̳ο sleep 120 Ѵ.  
 ڵ,   Ű  ϴ IRQ, IRQ 1 ִ. Ű 
ͷƮ ϸ, Ű ¸ а(inb(0x64) ̿ȴ) Ű忡 ϵ 
 Ѵ.  Ŀ ̿ Ű ڵ(ĵ ڵ ó 7 Ʈ) , 
 ų(8° Ʈ 0̸) Ǵ ( 1̸), got_char 
. 

<intrpt.c>

/* intrpt.c - ͷƮ ó */ 

/* Copyright (C) 1998 by Ori Pomerantz */ 

/* ʿ  ϵ   */ 
/* Ŀ ⿡ ǥ  */ 
#include <linux/kernel.h> 	/* Ŀ ۾ Ѵ. */ 
#include <linux/module.h> 	/* Ư,  */ 

/* CONFIG_MODVERSIONS ٷ */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include <linux/modversions.h> 
#endif 
#include <linux/sched.h> 
#include <linux/tqueue.h> 

/* ͷƮ Ѵ. */ 
#include <linux/interrupt.h> 
#include <asm/io.h> 

/* 2.2.3 /usr/include/linux/version.h ̸  ũθ Ѵ. 
׷, 2.0.35   ʿ 쿡 ̰ ߰Ѵ.*/ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 

/* Bottom Half -  ϰ   ϵ  Ŀ ⿡  
ǰ Ŀο  ȣǾ Եȴ. */ 
static void got_char(void *scancode) 
{ 
	printk("Scan Code %x %s.\n", 
           (int) *((char *) scancode) & 0x7F, 
           *((char *) scancode) & 0x80 ? "Released" : "Pressed"); 
} 

/*  Լ Ű ͷƮ Ѵ. Űκ   а Ŀ
 ϴٰ   ϱ  'bottom half'  ȴ. */
void irq_handler(int irq, void *dev_id, struct pt_regs *regs) 
{ 
	/* 
    'bottom half' ͸  ν ʿ䰡 ֱ⿡   ̴.
    */
    static unsigned char scancode; 
    static struct tq_struct task = 
    {
    	NULL, 
        0, 
        got_char, 
        &scancode
    }; 
    unsigned char status; 
        
    /* Ű ¸ б */ 
    status = inb(0x64); 
    scancode = inb(0x60); 
        
    /* 'bottom half' Ǳ   */ 
    #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) 
    queue_task(&task, &tq_immediate); 
    #else 
    queue_task_irq(&task, &tq_immediate); 
    #endif 
    mark_bh(IMMEDIATE_BH); 
} 

/*  ʱȭ - IRQ ó  */ 
int init_module() 
{ 
	/* 
    Ű ͷƮ óⰡ ٸ ó Բ   Ƿ, ⿡ 
	ó, ۾ ϱ  ̰ Ҵ(free irq)  ؾѴ. ̰  
	 𸣹Ƿ, ߿ ·   Եȴ -  ǻʹ  
	 õ  ̴.   
    */ 
    free_irq(1, NULL); 

    /* IRQ 1 û, Ű IRQ, irq_handler  . */ 
    return request_irq(1,irq_handler,SA_IRQ,"test_keyboard_irq_handler", NULL"); 
        
    /*
    1			- Ű IRQ ȣ  
    irq_handler - ó  
    SA_SHIRQ    - SA_SHIRQ  IRQ󿡼 ٸ ó⸦   ִٴ ǹ.
    SA_INTERRUPT  ͷƮ ó⸦   ̿. 
    */
} 

/*  */ 
void cleanup_module() 
{ 
    /*
    ̰  Ϻ   ִ ̴. ̰  ϸ,
    Ű ͷƮ     Ƿ ǻʹ    
	ǰ  õǾ߸ Ѵ.
    */    
    free_irq(1, NULL); 
} 

 12  

Ī  μ 

ϵ  ϴ  ս  ϳ    CPU  
ϴ ̴. ̰ ٸ CPU  ۾ ϰ ϰų(Ī  
) Ǵ  ۾ ķ ϰ   ִ(Ī  μ, S-
MP). Ī  μ ȿ ϱ ؼ ǻͰ ؾ  ½
ũ鿡  Ư  䱸Ǹ,   Ϲ   ü
 ʴ. ޸ ϸ, Ī  μ     
.  , Ȯ ǹ̴ --- δ   ʴ. Ī  
 ȯ濡, CPU  ޸𸮸 ϸ, ϳ CPU   ٸ 
CPU ̿Ǵ ޸𸮿  ĥ  ִ.  ̻     
  Ȯ   --- ǰ  ʴ ȿ ٸ CPU װ ٷ
 𸥴. ϰ, ó ϴ α׷ Ұϴ. μ  
 ϳ CPU  ̱⿡, ̷  μ α׷ ⿡
ٷ  ƴϴ. ٸ , Ŀ, ٸ CPU󿡼 Ǵ ٸ μ 
 ȣǾ ̴.  2.0.x, ü Ŀ ϳ Ŵ   
⿡  ɰ . ̴ ϳ CPU Ŀ ϰ, ٸ CPU ̰
 ϸ,   ý ȣ , ٸ CPU  CPU ϷǱ ٸ
ȴ. ̴  SMP ϰ ,   ȿ̴(*1). 
 2.2.x,   CPU ÿ ϳ Ŀ ϴ  ϴ.
׷  ۼڵ ̰   ʿ䰡 ִ. SMP 踦 ϳ ԵǾ⿡, 
 å    ڼ    ֱ⸦ ٶ.

1 *************************************************************************
̰ ܴ  CPU ѹ    μ̴,  ̰
 SMP Բ ̿ص ϴ.
*******************************************************************************

 13   

ϱ  Ǽ  

     ׸ Ŀ  ۼϴ  ˷־, 
⿡   ʿ䰡  ˷ְڴ.   ϰų  
  ,   ˷ ޶.

1. ǥ ̺귯 ̿ Ұϴ. Ŀ ⿡  Ŀ Լ ̿
ϸ, ̵ Լ /proc/ksyms   ִ.

2. ª ð   ʿϸ ͷƮ Ҵ ص ȴ. ׷, ߿ 
ͷƮ   , ý ȭǰ  ߸ ϰ ȴ.

3. Ŀٶ  տ  . Ƹ ̰Ϳ    ϰ, 
 ̰ ˾Ƴ 쿡 ׷  ̴. 


η A 

2.0 2.2 ȭ

    ü Ŀ  ؼ 밡 𸣰ڴ. 
 ȯ (, Emmanual Papirakis  ) Ʒ  
Ƴ. ޵    α׷ӿ  ֱ , Ư  å
    ߴ α׷ӿ  ̰ ο  
ȯ ̿  κ ϴ. 2.2 ȯ ϴ   ߰ 
 http:://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.2.html  
 ִ.

1. asm/uaccess.h - put_user get_user ʿϸ ̰ #includeؾ Ѵ.

2.  2.2 get_user -  get_user  ޸ Ϳ  ä 
    Ŀ ޸  ڷ ´. get_user   2 Ȥ 4Ʈ 
   ̸ ÿ 2 Ȥ 4 Ʈ д  ϴ. 

3. file_operations -  ü  open close flushԼ .

4. file_operations close -  2.2, closeԼ integer ϰ,
   fail  㰡Ǿ .

5. file_opearations read write - ̵ Լ   Ǿ. 
    ̵ integer ſ ssize_t ϰ, ̵  Ʈ ٸ. in-
   ode  ̻ ڰ ƴϸ, ϳ offset ߰Ǿ. 

6. proc_register_dynamic -  Լ  ̻  ʴ´. ſ, proc_regi-
   ster ȣ  ְ ü indoeʵ ȿ 0 Ѵ. 

7. Signals - ü ýε  ̻ 32Ʈ integer ƴϸ, NSIG_WORDS
   迭 interger̴. 

8. queue_task_irq - ͷƮ óȿ ½ũ ϱ ϸ queue_task
    ̿Ѵ. queue_task_irq ̿  . 
   
9.  ڵ -  ̻  ڸ    ʿ䰡 . 2.2 
   ׵   MODULE_PARM ̿ؾ Ѵ. ̰   Ǿ
   , ȥ  Ʈ Բ ϴ stringڵ  㰡Ѵ. 

10. Ī  μ - Ŀ ο  ̻ Ŵ    ʴ
    . Ŀ  SMP νؾ Ѵ.  
   
η B 

𿡼 ߰    ִ°? 

 å       ־ 𸣰ڴ. ο  ý 
, ο  ÿ   ߰ϰ ;. Ʈ Ʈ̳ ũ
̽ , ⼭ ٷ  Ŀ Ŀ   ߰ϰ 
;. ׷, ̷  ʾҴ.   å   Ŀ  α׷
   ˸ ⺻  ġ ̾. 
Ŀ α׷ֿ     , http://jungla.dit.upm.
es/~jmseyas/linux/kernel/hackers-docs.htm ҽ 캸 õѴ. , 
 ߵ, Ŀ ϴ    Ŀ ҽ ü  ̴
.   Ŀ   캸 ϸ, Phrack  õѴ. 
   , Ŀ  Ŀ ο   ϴ  
    , ̵ ϴµ ū  䱸 ʴ´. 
  α׷Ӱ Ǳ     ̶ ־ ٶ, 
    ణ ̸  ٶ. ׸,   Ŀ 
 ۼϰ Ǹ, GPLϿ ϱ ٶ,   ׷  ̴.

η C 

ǰ   

I hope nobody minds the shameless promotions here. They are all things which 
are likely to be of use to beginning Linux Kernel Module programmers. 

C.1 Ʈ ¹   

The Coriolis group is going to print this book sometimes in the summer of '99.
If this is already summer, and you want this book in print, you can go easy on 
your printer and buy it in a nice, bound form. 
 
η D 

 ȣǸ ̷  

This is a free document. You have no obligations beyond those given in the GNU 
Public License (Appendix E). However, if you want to do something in return 
for getting this book, there are a few things you could do. 

Send me a postcard to 
Ori Pomerantz 
Apt. #1032 
2355 N Hwy 360 
Grand Prairie 
TX 75050 
USA 

If you want to receive a thank-you from me, include your e-mail address. 
Contribute money, or better yet, time, to the free software community. Write a
program or a document and publish it under the GPL. Teach other people how to 
use free software, such as Linux or Perl. 
Explain to people how being selfish is not incompatible with living in a 
society or with helping other people. I enjoyed writing this document, and 
I believe publishing it will contribute to me in the future. At the same time, 
I wrote a book which, if you got this far, helps you. Remember that happy people 
are usually more useful to oneself than unhappy people, and able people are way 
better than people of low ability. 

Be happy. If I get to meet you, it will make the encounter better for me, it will make 
you more useful for me ;). 

η E

GNU General Public License

This is an unofficial translation of the GNU General Public License into  Korean. It was 
not published   by the  Free  Software  Foundation,  and does   not legally   state the 
distribution terms for software that uses the  GNU GPL--only the original English text 
of the GNU  GPL does  that. However,  I hope that  this translation  will help  Korean 
speakers understand the GNU GPL better.

   Ʈ (Free Software Foundation) GNU General Public 
License ѱ  ̴.   GNU General Public License 
 ִ ȣ      鿡 ˸   
ۼǾ  Ʈ    ޵  . ̴  
 ǵϰ ִ  ְ ʰ  ȿϱ ؼ Ǿ 
 籹    ռ ο    ۾  
 ʿϱ ̴. ,  Ʈ  ̳ ؼ 
ؼ ߻    ɼ ̿ ϰ   ִ  
   鿡 ȫϷ ݵ  ѱ   
 ν 縳ų   ̴. 
 Ʈ  GNU General Public License ǹ  ,  
 GNU General Public License ؼ    ȿ ùٸ ߻ 
  ǰϰ ִ.      ϼ ο  
 ġ  ̸ ̷ ؼ ߱       
ؼ     ʴ´. 

Original Copy: GNU General Public License 

Korean Translator: 1998 Song Changhun â mailto:chsong@cyber.co.kr 

 

* GNU GENERAL PUBLIC LICENSE 
*  ( ) 
*  ,   ǰ  
* GPL ǹ ϴ  

GNU GENERAL PUBLIC LICENSE

Version 2, June 1991 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

۱ǰ  㰡    õǴ ,
  ü   糪 鵵  ȴ.
,    ÷  ʴ´.

  ( )

Ʈ  κ ̼ ش Ʈ    
 Ϸ    Ѵ. ׷, GNU General Public License  
Ʈ     ȣ ϱ ؼ Ǿ. 
 Ʈ  ϴ κ Ʈ GNU General Public License
  ؼ ǰ      ȿ̶ ǴܵǴ 
̺귯 ƾ(library subroutine) ,   GNU Library Gener-
al Public License  ϰ ִ.  Ʈ ̸ Ϸ 
 ؼ   ϸ Բ 絵Ǵ Ʈ ǹϸ α
    α׷     ִ. 
 Ʈ   Ǵ '' ܾ ǹ̴   
 ƴ ӵ ʴ´ٴ   ǹϸ GNU General Public Licen-
se  Ʈ ̿  ,       
   Ѵ. ⿡ ҽ ڵ  Ǵ Ϻθ ؼ
 α׷ Űų ο α׷ â  ִ  Ե
 ڽſ 絵 ̷  Ǹ  Ȯϰ ν  ֵ ϱ 
   ԵǾ ִ. 
GNU General Public License   Ʈ Ǿ絵 Ǹ ϴ Ư
 װ ܼ  ÷Ű ϰ ν ڵ  
 Ǹ ϰ ִ.  Ʈ ۰  ϰ ִ 
̷  Ǹ 絵  ؼؾ߸ Ѵ. 
 , Ư α׷   絵ڴ Ǿ絵ڿ ڽ 絵޾Ҵ 
 Ǹ  ο  ״ ؾ߸ Ѵ. ҽ ڵ忡   
Ǹ  ⿡ ԵǾ ϸ ̿  ׵ ν Ǿ絵ڵ鿡 
׵ 絵 Ǹ   ֵ ؾ Ѵ. 
 Ʈ       ؼ ݺǴ 絵  
  Ǹ ȣѴ: (1) ۱ ν α׷ ڵ Ǹ
 ȣѴ. (2) ۱ 絵   ؼ ȿ  ȿ 
GNU General Public License ؼ Ʈ  ,    
Ʈ Ǿ絵 Ǹ  Ѵ. 
 Ʈ ڵ  絵  ؼ Ʈ ü 
    ߻   ̴  ڿ  Ʈ 
  ƴ  ִٴ  ؼ νϰ ־ Ѵ. GNU General Publ-
ic License  Ʈ        
  Ǿ ̸ ̴ α׷ ڿ  Ʈ 
ο Ȱ ϴ  ̱⵵ ϴ. 
Ư   Ʈ  ϴ  ۿ . , 
Ʈ      Ư㸦  ۹ Բ ԽŰ
 ν ̿   ѵ ʵ ϴ  ּ ̴. GNU G-
eneral Public License ̷  óϱ ؼ Ư㰡  ۹  
̼ Ư ټ(, ""̶ Ѵ)  ϴ 쿡 
ؼ  Ʈ Բ   ֵ ϰ ִ. 

(copying) (modification), (distribution)  õ ü 
   . 

 ,   ǰ 

 0 .  ̼ GNU General Public License     ִ
  ۱ڿ ؼ õ  ǻ α׷ ۹ ؼ ϰ
ȴ. ǻ α׷ ۹(, "α׷"̶ Ѵ)̶ Ư α׷
 ̿ õ Ÿ ۹ ǹϰ "2 α׷"̶ ۱ǹ  
 α׷  Ǵ  κ ϰų ٸ α׷   
  ִ   ؼ â۵ ο α׷ ̿ õ ۹
ǹѴ(ķ ٸ α׷   ٸ     
ԵǴ  Ѵ) "Ǿ絵" GNU General Public License  
 α׷ 絵  ǹѴ. 
 ̼ α׷   ,   ؼ ȴ. 
, α׷ Ű  ѵ  α׷ ࿡   
 ü    ο   2 α׷ 
 ؼ  ̼    ִ. 2 α׷  δ 
2 α׷ ȿ α׷   ǴѴ. 

 1 .Ǿ絵ڴ α׷    ʴ´ٴ ǰ ۱ Բ
ϴ , 絵 ҽ ڵ  Ǵ Ϻθ   ü ؼ 
ؼ   ִ. Ǿ絵ڰ α׷ ҽ ڵ带   α
   ῩǾ ִٴ ǰ  ̼ ؼ  ׵ 
 ״ Ѿ ϸ GNU General Public License  Բ ؾ 
.   ,  ϱ ؼ ҿ  ϱ ؼ
  Ǹ    Ǹſ   ȯ ϴ 
    ִ. 

 2 . Ǿ絵ڴ ڽ 絵 α׷  Ǵ Ϻθ   
̸ ؼ 2 α׷ â  ִ. ۵ α׷̳ â۵ 2 
α׷ ҽ ڵ  1   ؼ  ׵ Ű ǿ 
ؼ ؼ   ִ. 
* a) ۵   ۵ ǰ ۵ ¥  Ȯε  ֵ
 ۼǾ Ѵ. 
* b) ϰų Ϸ ۹  Ǵ Ϻΰ 絵 α׷ κ
Ļ ̶ ۵ α׷  ̳ ǹ  ü   Ǹ
 ߿  ؾ Ѵ. 
* c) ۵ α׷ Ϲ  ° ɾ Է Ŀ  ȭ  
 , ۵ α׷ ̷ ȭ  ϰ  Ǿ  ۱ǿ 
 װ α׷   ῩǾ  ٴ  ۵ α׷ 
̼  ؼ ٽ  ؼ   ִٴ װ GNU General Pub-
lic License   ִ  Բ  Ŀ  Ǵ ȭ ؼ 
µ  ֵ  ۼǾ Ѵ( : 絵 α׷ ȭ  
߰ ִ ϴ   ȯ濡  ׵ µ ʴ ¿
, ̸  α׷   ׵ ½ Ű ʾƵ ȴ) 
 ׵ ۵ κ Ե 2 α׷ ü ȴ. ,  
۹ 2 α׷ ԵǾ ִ κа  ̶ ϴ װ 絵
 α׷κ Ļ  ƴ϶   ۹   
  ,  ۹     ̼  
 ʴ´. ׷, ̷ ۹ 2 α׷ ԵǾ Բ ȴٸ 
 ۱ǰ  ؿ   ü ۹ ΰ  ̼
ؼ Ǿ ϸ ü ۹ Ϻ Ǵ ο    Ǹ
߿  絵Ǿ Ѵ. 
̷   ۹  ۱ Ǹ ҽŰ  ƴ϶ 
2 α׷κ ݺ Ļǰų ̷ α׷   
 ؼ  ̼  ϰ ϱ  ̴. α׷(Ǵ
2 α׷) ܼ ϰų   Բ    
 Ļ ۹  ʴ   ̼ ؼ ȴ. 

 3 . Ǿ絵ڴ    ϳ Ű ǿ ؼ  1 װ 
2    α׷(Ǵ  2    2  α׷) 
ڵ峪  · ؼ   ִ. 
* a)  ڵ峪  ¿ شϴ ҽ ڵ θ  1 װ  2  
  ǻͰ Է¹ްų   ִ · Ʈ   
 Ϲ Ǵ  ü ؼ Բ  ؾ Ѵ. 
* b)  ڵ峪  ¿ شϴ ҽ ڵ θ ּ 3 ̻ 
 ִ μ⹰ ·  1 װ  2    Ʈ  
ؼ Ϲ Ǵ  ü ؼ  Ǻ ϴ 븸 ΰؼ
߿ 絵  ֵ Բ ؾ Ѵ. 
* c)  ڵ峪  ¿ شϴ ҽ ڵ θ   ִ  
  Բ ؾ Ѵ( ׸ 񿵸  ׸ b) ؼ  
ڵ峪          ִ) 
۹  ҽ ڵ ش ۹ ϱ ؼ Ϲ ȣǴ ǥ
 ǹϰ ๰  ҽ ڵ ùٸ Ǳ ؼ ʿ 
̽  , ϰ ġ ؼ ʿ ũƮ   Ѵ. 
׷, Ϸ Ŀΰ  ü ֿ κе鿡  ҽ ڵ峪 ̳
´ α׷ ̷ κе   ʴ  Բ  ʾƵ 
ϴ.  ڵ峪  ¸ Ư ҷκ   ֵ ϴ 
  ,  ҷκ ҽ ڵ带   ֵ ϴ  
Ǿ絵ڿ ҽ ڵ带  ڵ峪  ¿ Բ     
Ҵ ϴ ҽ ڵ带 Բ ϴ  Ѵ. 

 4 .  ̼ ؼ  α׷ 絵 ʾҴٸ 絵 
α׷   ,  ̼       . 
̿ õ    ȿ̸  ̼ ϰ ִ 
  Ǹ ڵ Ҹȴ. ,  ̼   ʰ 絵
 α׷̶ ϴ ̸  ̼ 絵   ٽ 
, α׷ ٽ 絵  3 Ǿ絵ڴ  ̼ ؼϴ Ͽ
  Ǹ   ִ. 

 5 . Ǿ絵ڴ α׷ 絵   ̼  ν 
̼  ޾Ƶ   ִ.  , Ǿ絵ڿԴ α׷
 ܼ 븸 Ǹ α׷ 2 α׷  ۰  
  ʴ´. ̴ Ǿ絵ڰ ̼  ν ߻ 
 ̴. , α׷(Ǵ 2 α׷) ϰų ϴ 
  ,    ̼  ǵ  ޾Ƶ̰ڴٴ 
 Ƿ Ѵ. 

 6 . Ǿ絵ڿ ؼ α׷(Ǵ 2 α׷) ݺ  
,  ܰ迡 Ǿ絵ڴ  ̼   α׷  ,
    α׷ 絵ڷκ 絵  ڵ 
ȴ. α׷(Ǵ 2 α׷) 絵  Ǿ絵 Ǹ   
  ׵  ÷      ̼  ؼ
ϵ   . 

 7 .  ǰ̳ Ư ħؿ   Ǵ Ư  ѵ ʴ
  ٸ  ؼ  ̼  ġǴ  ߻Ѵ ϴ
  ̼ ġǴ   ̼    켱  
 ʴ´. ,  ̳   ؼ  ̼ Ǵ
׵ ΰȴ ϴ  ̼  Բ Ű鼭 ش α
   ٸ  α׷  ȴ.  , Ư Ư 
̼  Ǵ  絵  ؼ α׷  ϴ 
  ʴ´ٸ  α׷  ̼  ؼ Ǵ α׷
 Բ   . Ư Ȳ   Ϻκ    쿡
 ش κ   κе Ű   θ Ű 
ؼ ٸ Ȳ ǵ ʿϴ.    Ư㳪  ħ  
 ϰų ش Ǹ    ƴ϶ GNU General Public 
License   ؼ  Ʈ  ü踦  ȣ
  ̴.    ü迡  ŷִ   ν 
Ʈ پ о߿    ־. Ʈ   ü
 ؼ  ΰ ϴ   ڿ   ޷
 Ϲ ڵ   ִ  ƴ ̴.   ӵǴ  
̼  ؼ ߿ϰ ޵ǰ ִ   Ȯϰ ϴ 
  ̴. 

 8 . Ưǰ ۱  ó Ŀ ؼ Ư  α׷ 
  Բ Ǵ   ,  ̼ ؼ α׷ 
 ڴ  ߻ ʴ  ؼ ̸ Ѵٴ   
     ̷   ̼ Ϻη ֵȴ. 

 9 .  Ʈ  GNU General Public License ϰų  
 ִ. ǰų Ǵ  ο  ɿ   
ǰ  ٺ  ٲ  ̴. 
GNU General Public License   ٸ  ȣ  ̴. 絵
 α׷ Ư  ̼ ϰ ִٸ ش  Ǵ   
̼ Ǹ       ̼ 
 ϴ. 

 10 . α׷ Ϻθ  ̼   ٸ  α׷ Բ 
 , ش α׷ ڷκ    ޾ƾ Ѵ.  
Ʈ  ۱  ִ Ʈ ϱ ؼ  Ʈ
    Ѵ.  Ʈ   ǿ ؼ  
   ִ.  Ʈ   Ʈ 2 ۹ 
 ο · Ű  Ʈ Ϲ  Ȱ 
Ű ؿ ٰؼ  θ  ̴.

 Ῡ 

 11 .  ̼  α׷  絵ǹǷ   ϴ
ѵ      ʴ´. , α׷ ۱ڿ 
3 ڿ ؼ  Ǵ  Ư   α׷ ռ 
θ ϱ  쳪  Ǹſ    ȴٴ  
 õǾ ִ  ܷ Ѵ.  쵵 ش α׷ ü  
 ٿ  Ῡ   . α׷ α׷ ࿡  
  ִ   Ǿ絵ڿ μǸ ̿      
    Ǿ絵ڰ δѴ. 

 12 . ۱ڳ  3 ڰ α׷ ջ ɼ  ˰ ־
ϴ ߻ ս  Կ ؼ ȣǰ ְų ۱ڳ α׷ 
ü    ʴ´ٴ  α׷ ۵ α׷ Բ Ǵ
  ڰ     찡 ƴ϶ α
 ̳  ̼ ؼ ߻ ս  Ǿ絵 å̴. 
߻ ս Ϲݼ̳ Ư Ӹ ƴ϶  ߼  ʿ  
ʴ´. 

 ,   ǰ  .

 ǹ ϴ 

 α׷   鿡 ϰ Ǳ⸦ Ѵٸ  α׷
  ̼   Ӱ ǰ   ֵ  Ʈ
   ּ ̴. 
  ׵ α׷ ÷ν ش α׷  Ʈ 
  ִ. α׷    ʴ´ٴ   ȿ 
  ִ  ҽ ڵ尡 ԵǾ ִ    κп ̷ 
׵ ϴ ̴.  ϵ ּ ۱ǰ GPL   ִ 
 ؾ߸ Ѵ. 

α׷ ̸ 뵵   ؼ   Ѵ.
Copyright (C) 19yy  α׷  ̸

 α׷  Ʈ̴. Ʈ Ǿ絵ڴ  Ʈ 
 GNU General Public License  ؼ  α׷ ۵ 2 α
 Բ Ǵ    ִ.

 α׷  ϰ     ǰ  ǰ 
     ʴ´.  ڼ ׿ ؼ GNU General 
Public  License ϱ ٶ.

GNU General Public License  α׷ Բ ȴ. 

,   Ǿ ִٸ  Ʈ ܿ ϱ ٶ( 
Ʈ : Free  Software Foundation, Inc., 59 Temple Place - Suite 330, Bost-
on, MA 02111-1307, USA)

, α׷ ڿ  Ǵ   ؼ   ִ  
ؾ Ѵ. 

,  α׷ ɾ Է Ŀ  ȭ  ϰ ִٸ α׷
 ȭ  Ǵ ʱ ¿     ½Ѿ 
. 

Gnomovision version 69, Copyright (C) 19yyα׷  ̸ 
Gnomovision ǰ      ʴ´. 

 ڼ  'show w' ɾ ̿ؼ õ    ٶ.
 α׷  Ʈ̸ Ư  Ű Ͽ 
 ִ.   ش  'show c' ɾ ؼ   ִ. 
'show w' 'show c' General Public License ش κ ϱ  
ɾ̴. ,  ɾ 콺 ̿ϰų ޴  ϴ 
α׷        ̴. , α׷ 
ڰ б   ü  Ǿ ִٸ α׷ ο 
ؼ ֳ ش   α׷  ۱ Ѵٴ Ǹ
 Ѵ.  ,      ִ. 

 James Hacker ؼ ۼ
'Gnomovision' α׷    ۱ Ѵ. 
1989 4 1
Yoyodye, Inc., λ: Ty Coon
:  Ty Coon   

 ̼  Ʈ  α׷  Ʈ Բ 
   ʴ´. , ۼ α׷ ̺귯 ƾ  
׷ 쿡 ̸  Ʈ   α׷ Բ ν 
 ȿ Ȱ  ִٰ    ̴. ̷   ̼
 ſ GNU Library General Public License ν ұ  
ų   ̴. 
                                                
