IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  리눅스  >

/proc 파일 시스템을 활용한 리눅스 커널 접근

/proc 가상 파일 시스템은 커널과 사용자 영역 사이에서 통신이라는 윈도우를 열어준다

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

영어원문

영어원문


제안 및 의견
피드백

난이도 : 초급

M. Tim Jones, 컨설턴트 엔지니어, Emulex Corp.

옮긴이: 박재호 이해영 dwkorea@kr.ibm.com

2008 년 11 월 11 일

/proc 파일 시스템은 리눅스(Linux®) 커널과 사용자 영역 사이에 일어나는 통신 채널을 제공하는 멋진 가상 파일 시스템입니다. /proc 파일 시스템에서, 커널 구성 요소와 통신하는 수단으로 가상 파일을 읽고 쓸 수 있습니다. 하지만 일반 파일과는 달리 이런 가상 파일 내용은 동적으로 만들어집니다. 이 기사에서는 /proc 가상 파일 시스템을 소개하고 활용 방법을 보여줍니다.

원래 /proc 파일 시스템은 시스템에서 프로세스 정보를 제공하기 위해 개발되었다. 하지만 /proc 파일 시스템이 제공하는 유용성 때문에 커널에 포함된 여러 구성 요소가 정보 보고와 동적 실행 설정 목적으로 /proc을 활용한다.

/proc 파일 시스템은 (정보를 조직적으로 관리하는 수단으로) 디렉터리와 가상 파일을 포함한다. 가상 파일은 커널에서 사용자 영역으로 정보를 제공할 수 있으며, 사용자에서 커널 영역으로 정보를 보낼 수도 있다. 실제 환경에서 양쪽 모두를 요구하지 않더라도, 이 기사에서는 설명을 위해 입출력을 위한 /proc 파일 시스템 설정 방법을 보여준다.

이 기사처럼 짧은 내용을 다루는 글에서 /proc 활용법을 자세히 설명하기는 어렵기에 /proc이 얼마나 강력한지 힌트를 주는 몇 가지 용법을 소개하겠다. Listing 1은 몇 가지 /proc 구성 요소를 보여주는 상호대화식 예제를 보여준다. Listing 1은 /proc 파일 시스템의 루트 디렉터리를 보여준다. 왼쪽에 등장하는 번호가 부여된 일련의 파일에 주목하자. 각각은 시스템에서 돌아가는 프로세스를 나타내는 디렉터리다. GNU/리눅스에서 처음으로 만들어지는 프로세스가 init이므로, pid가 1이 붙어 있다. 다음으로 ls 명령을 사용해 파일 목록을 살펴본다. 각 파일은 특정 프로세스에서 세부 사항을 제공한다. 예를 들어, init을 위한 명령행 항목을 보려면 cat cmdline 파일을 입력하기만 하면 된다.

/proc에서 다른 흥미로운 몇몇 파일은 프로세서 유형과 속력을 파악하는 cpuinfo, PCI 버스에 물린 장비를 보여주는 pci, 현재 커널에 올라온 모듈을 파악하는 modules 등이 있다.


Listing 1. /proc 상호대화식 예제
        
[root@plato]# ls /proc

1     2040  2347  2874  474          fb           mdstat      sys

104   2061  2356  2930  9            filesystems  meminfo     sysrq-trigger

113   2073  2375  2933  acpi         fs           misc        sysvipc

1375  21    2409  2934  buddyinfo    ide          modules     tty

1395  2189  2445  2935  bus          interrupts   mounts      uptime

1706  2201  2514  2938  cmdline      iomem        mtrr        version

179   2211  2515  2947  cpuinfo      ioports      net         vmstat

180   2223  2607  3     crypto       irq          partitions

181   2278  2608  3004  devices      kallsyms     pci

182   2291  2609  3008  diskstats    kcore        self

2     2301  263   3056  dma          kmsg         slabinfo

2015  2311  2805  394   driver       loadavg      stat

2019  2337  2821  4     execdomains  locks        swaps

[root@plato 1]# ls /proc/1

auxv     cwd      exe  loginuid  mem     oom_adj    root  statm   task

cmdline  environ  fd   maps      mounts  oom_score  stat  status  wchan

[root@plato]# cat /proc/1/cmdline

init [5]

[root@plato]#


Listing 2는 /proc에서 읽고 쓰는 예를 보여준다. 이 예는 커널 TCP/IP 스택 내부에서 IP 포워드를 점검하고 활성화하는 방법을 보여준다.


Listing 2. /proc 읽고 쓰기(커널 설정)
        
[root@plato]# cat /proc/sys/net/ipv4/ip_forward

0

[root@plato]# echo "1" > /proc/sys/net/ipv4/ip_forward

[root@plato]# cat /proc/sys/net/ipv4/ip_forward

1

[root@plato]#


대안으로, sysctl을 사용해 이런 커널 구성 요소를 설정할 수도 있다. 추가 정보는 참고자료 절을 참조하자.

그런데, /proc 파일 시스템은 GNU/리눅스에서 유일한 가상 시스템이 아니다. sysfs는 /proc과 비슷하지만 좀 더 조직화되어 있다(/proc에서 교훈을 얻었기 때문이리라). 하지만 /proc은 개발자 사이에 깊숙히 자리잡은 터라 sysfs가 /proc에 비해 장점이 있음에도 불구하고 여전히 팔팔하다. 또한 debugfs 파일 시스템도 있지만, (이름이 의미하는 바와 같이) 디버깅 인터페이스로 더 많이 사용되는 경향이 있다. debugfs의 장점은 엄청나게 간단하므로 (호출 하나로) 사용자 영역에 값 하나를 공개할 수 있다.

커널 모듈 소개

LKM(Loadable Kernel Module)은 /proc 파일 시스템 활용법을 보여주는 좋은 예다. 리눅스 커널에서 동적으로 코드를 넣고 빼는 참신한 기법이기 때문이다. LKM은 리눅스 커널에서 디바이스 드라이버와 파일 시스템을 위한 인기 있는 메커니즘이기도 하다.

리눅스 커널을 새로 컴파일해 봤다면, 커널 환경 설정 과정에서 여러 가지 디바이스 드라이버와 기타 커널 구성 요소를 모듈로 컴파일한다는 사실을 발견했을 것이다. 드라이버가 커널에 직접 결합되는 방식으로 컴파일되면, 해당 모듈의 코드와 정적 자료는 사용하지 않더라도 공간을 차지한다. 하지만 드라이버를 모듈로 컴파일하면, 모듈이 커널에 올라올 때만 필요한 메모리를 할당한다. 흥미롭게도, LKM은 커널 성능에 영향을 미치지 않으므로 하드웨어와 연결된 장비 상태를 기반으로 환경에 맞춤식으로 다이어트한 커널을 생성하는 강력한 수단이 된다.

리눅스 커널에서 찾을 수 있는 표준(동적 적재가 가능하지 않은) 코드와 다른 점을 이해하도록 돕기 위해 간단한 LKM을 여기에 실어보았다. Listing 3은 가장 간단한 LKM을 보여준다(다운로드 절에서 이 기사를 위한 예제 코드를 내려받을 수 있다).

Listing 3은 필요한 모듈 헤더를 포함한다(여기서 모듈 API, 타입, 매크로를 정의한다). 그러고 나서 MODULE_LICENSE를 사용해 모듈 라이선스를 정의한다. 여기서는 커널 오염을 막기 위해 GPL을 명시했다.

그런 다음 Listing 3에서 모듈 initcleanup 함수를 정의한다. my_module_init 함수는 모듈이 메모리에 올라올 때 호출되며, 이 함수는 초기화 목적으로 쓰인다. my_module_cleanup 함수는 모듈이 메모리에서 내려갈 때 호출되며, 메모리를 해제하며 모듈 추적을 제거하는 데 쓰인다. 여기서 printk 사용법에 주목하자. 이 함수는 커널용 printf 함수다. KERN_INFO 심볼은 (syslog와 흡사하게) 커널 링 버퍼로 들어가는 정보를 필터링할 목적으로 쓰이는 문자열이다.

마지막으로 Listing 3은 module_initmodule_exit 매크로를 사용해 entry와 exit 함수를 선언한다. 이는 모듈 initcleanup 함수 이름을 원하는 방식대로 지정하도록 만들기에 모듈과 관련해 어떤 함수에 주목해야 할지 커널에 알려준다.


Listing 3. 간단하지만 동작하는 LKM(simple-lkm.c)
        
#include <linux/module.h>



/* LKM을 위한 라이선스 정의 */

MODULE_LICENSE("GPL");



/* 모듈 진입시 호출될 init 함수 */

int my_module_init( void )

{

  printk(KERN_INFO "my_module_init called.  Module is now loaded.\n");



  return 0;

}



/* 모듈이 빠져나갈 때 호출될 cleanup 함수 */

void my_module_cleanup( void )

{

  printk(KERN_INFO "my_module_cleanup called.  Module is now unloaded.\n");



  return;

}



/* entry와 exit 함수 정의 */

module_init( my_module_init );

module_exit( my_module_cleanup );


Listing 3은 단순하긴 하지만 실제로 동작하는 LKM이다. 이제 2.6 커널에 맞춰 빌드해서 테스트할 시간이 왔다. 커널 2.6은 커널 모듈 빌드를 위한 새로운 방식을 도입했으며, 예전 방식에 비해 훨씬 더 단순함을 알 수 있다. simple-lkm.c를 대상으로 한줄로 이뤄진 makefile을 만들자.

obj-m += simple-lkm.o

LKM을 빌드하기 위해 Listing 4를 참고로 make 명령을 내려보자.


Listing 4. LKM 빌드하기
        
[root@plato]# make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules

make: Entering directory `/usr/src/linux-2.6.11'

  CC [M]  /root/projects/misc/module2.6/simple/simple-lkm.o

  Building modules, stage 2.

  MODPOST

  CC      /root/projects/misc/module2.6/simple/simple-lkm.mod.o

  LD [M]  /root/projects/misc/module2.6/simple/simple-lkm.ko

make: Leaving directory `/usr/src/linux-2.6.11'

[root@plato]#


빌드 결과로 simple-lkm.ko가 만들어진다. 새로운 이름 관례는 표준 목적 파일과 커널 목적 파일(LKM)을 구분하는 데 도움을 준다. 이제 모듈을 메모리에 올리고 내린 다음에 결과를 살펴보자. 모듈을 올리려면, insmod 명령을 내린다. 반대로 모듈을 내리려면, rmmod 명령을 내린다. lsmod는 현재 메모리에 올라온 LKM을 보여준다(Listing 5 참조).


Listing 5. LKM을 메모리에 올리고 상태를 점검하고 메모리에서 내리는 방법
        
[root@plato]# insmod simple-lkm.ko

[root@plato]# lsmod

Module                  Size  Used by

simple_lkm              1536  0

autofs4                26244  0

video                  13956  0

button                  5264  0

battery                 7684  0

ac                      3716  0

yenta_socket           18952  3

rsrc_nonstatic          9472  1 yenta_socket

uhci_hcd               32144  0

i2c_piix4               7824  0

dm_mod                 56468  3

[root@plato]# rmmod simple-lkm

[root@plato]#


커널 결과물은 표준 출력(stdout)이 아니라 커널 링 버퍼에 들어간다는 사실에 주의하자. stdout은 프로세스에 밀접한 개념이기 때문이다. 커널 링 버퍼에 들어있는 메시지를 검사하려면, dmesg 유틸리티를 사용한다(아니면 cat /proc/kmsg 명령을 내려 /proc 자체 기능을 활용하면 된다). Listing 6은 dmesg를 사용해 마지막 커널 메시지 몇 개를 보여준다.


Listing 6. LKM 커널 출력 결과 검토
        
[root@plato]# dmesg | tail -5

cs: IO port probe 0xa00-0xaff: clean.

eth0: Link is down

eth0: Link is up, running at 100Mbit half-duplex

my_module_init called.  Module is now loaded.

my_module_cleanup called.  Module is now unloaded.

[root@plato]#


커널 출력에서 모듈 메시지를 볼 수 있다. 이제 간단한 예제를 벗어나 실제 활용할 수 있는 LKM을 개발하도록 지원하는 몇 가지 커널 API를 살펴보자.




위로


/proc 파일 시스템에 통합하기

커널 프로그래머에게 공개된 표준 API는 LKM 프로그래머에게도 공개되어 있다. 심지어 LKM이 새로운 변수와 함수를 외부에 공개하고 커널이 이를 받아서 사용할 수도 있다. 완벽한 API 설명은 이 기사 범위를 벗어나므로, 나중에 좀 더 유용한 LKM을 소개하기 위한 몇몇 구성 요소만 간단하게 소개하고 넘어가겠다.

/proc 항목 생성과 제거

/proc 파일 시스템에 가상 파일을 생성하려면, create_proc_entry 함수를 사용한다. 이 함수는 파일 이름, 접근 권한, 파일이 위치할 /proc 파일 시스템 위치를 받는다. create_proc_entry 반환값은 proc_dir_entry 포인터(create에서 오류가 발생할 경우 NULL)다. 이 반환 포인터 값을 사용해 파일에 읽기 요청이 들어올 때 함수 호출을 수행하는 등 가상 파일의 다른 측면을 설정한다. create_proc_entry에 대한 프로토타입과 proc_dir_entry 구조 일부를 Listing 7에 정리했다.


Listing 7. /proc 파일 시스템 항목을 관리하기 위한 구성 요소
        
struct proc_dir_entry *create_proc_entry( const char *name, mode_t mode,

                                             struct proc_dir_entry *parent );



struct proc_dir_entry {

	const char *name;			// 가상 파일 이름

	mode_t mode;				// 접근 권한

	uid_t uid;				// 파일의 uid

	gid_t gid;				// 파일의 gid

	struct inode_operations *proc_iops;	// inode 연산 함수

	struct file_operations *proc_fops;	// 파일 연산 함수

	struct proc_dir_entry *parent;		// 어버이 디렉터리

	...

	read_proc_t *read_proc;			// /proc read 함수

	write_proc_t *write_proc;		// /proc write 함수

	void *data;				// 내부용 자료를 가리키는 포인터

	atomic_t count;				// 사용 횟수

	...

};



void remove_proc_entry( const char *name, struct proc_dir_entry *parent );


나중에 가상 파일을 읽고 쓰기 위한 함수를 연결하는 read_procwrite_proc 명령 사용법을 살펴보겠다.

/proc에서 파일을 삭제하려면, remove_proc_entry 함수를 사용한다. 이 함수를 사용하려면, /proc 파일 시스템에서 파일 위치(어버이)는 물론이고 파일 이름 문자열을 제공해야 한다. 이 함수 프로토타입도 Listing 7에 정리했다.

parent 인수는 /proc 루트일 경우 NULL이며, 파일을 위치하는 곳에 따라 다른 값도 될 수 있다. 표 1에 파일 시스템 위치에 따라 사용 가능한 어버이 proc_dir_entry 몇 가지를 정리했다.


표 1. 단축 proc_dir_entry 변수 요약
proc_dir_entry파일 시스템 위치
proc_root_fs /proc
proc_net /proc/net
proc_bus /proc/bus
proc_root_driver /proc/driver

write 콜백 함수

write_proc 함수를 사용해 /proc 항목(사용자 영역에서 커널 영역 방향으로)에 쓸 수 있다. 이 함수 프로토타입은 다음과 같다.

int mod_write( struct file *filp, const char __user *buff,

               unsigned long len, void *data );


filp 인수는 열린 파일 구조체다(여기서는 이 값을 무시한다). buff 인수는 전달될 문자열 자료다. 버퍼 주소는 실제로 사용자 영역 버퍼이므로 직접 읽을 수 없다. len 인수는 buff에 들어있는 자료 크기다. data 인수는 내부용으로 사용하는 포인터다(Listing 7 참조). 모듈에서, 들어오는 자료를 다루기 위해 이런 유형으로 함수를 선언했다.

리눅스는 사용자 영역과 커널 영역 사이에서 자료를 이동하기 위한 API 집합을 제공한다. write_proccopy_from_user 함수를 이용해 사용자 영역 자료를 처리한다.

read 콜백 함수

read_proc 함수를 사용해 (커널 영역에서 사용자 영역 방향으로) /proc 항목에서 자료를 읽을 수 있다. 이 함수 프로토타입은 다음과 같다.

int mod_read( char *page, char **start, off_t off,

              int count, int *eof, void *data );

page 인수는 사용자를 위해 자료를 쓸 수 있는 위치이며, count는 쓸 수 있는 최대 문자 개수를 정의한다. startoff 인수는 자료가 한 페이지(일반적으로 4KB) 이상 반환될 때 사용한다. 모든 자료를 쓰고 나면, eof(end-of-file) 인수를 설정한다. write과 마찬가지로 data는 내부용으로 사용하는 포인터다. 여기서 제공되는 page 버퍼는 커널 영역에 자리잡는다. 따라서 copy_to_user를 호출할 필요 없이 쓰기가 가능하다.

다른 유용한 함수

proc_mkdir을 사용해 /proc 파일 시스템에 디렉터리를 생성할 수 있으며, proc_symlink를 사용해 심볼릭 링크 생성도 가능하다. read 함수만 필요한 간단한 /proc 항목이라면, create_proc_read_entry를 사용한다. 이 함수는 /proc 항목을 생성한 다음에 호출 하나로 read_proc 함수를 초기화한다. 이 함수에 대한 프로토타입은 Listing 8에 정리했다.


Listing 8. 다른 유용한 /proc 함수
        
/* proc 파일 시스템에서 디렉터리를 생성한다. */

struct proc_dir_entry *proc_mkdir( const char *name,

                                     struct proc_dir_entry *parent );



/* proc 파일 시스템에서 심볼릭 링크를 생성한다. */

struct proc_dir_entry *proc_symlink( const char *name,

                                       struct proc_dir_entry *parent,

                                       const char *dest );



/* 호출 한번에 read_proc_t로 proc_dir_entry를 생성한다. */

struct proc_dir_entry *create_proc_read_entry( const char *name,

                                                  mode_t mode,

                                                  struct proc_dir_entry *base,

                                                  read_proc_t *read_proc,

                                                  void *data );



/* 커널 영역에서 사용자 영역으로 버퍼를 복사한다. */

unsigned long copy_to_user( void __user *to,

                              const void *from,

                              unsigned long n );



/* 사용자 영역에서 커널 영역으로 버퍼를 복사한다. */

unsigned long copy_from_user( void *to,

                                const void __user *from,

                                unsigned long n );



/* '가상'으로 연속된 메모리 블록을 할당한다. */

void *vmalloc( unsigned long size );



/* vmalloc으로 할당한 메모리 블록을 해제한다. */

void vfree( void *addr );



/* 커널로 심볼을 공개한다(커널에 심볼이 보인다). */

EXPORT_SYMBOL( symbol );



/* 파일에 있는 모든 심볼을 커널로 공개한다(module.h 전에 선언한다). */

EXPORT_SYMTAB





위로


/proc으로 행운의 쿠키 보기

지금부터는 읽기와 쓰기를 동시에 지원하는 LKM을 제시하겠다. 여기서 소개하는 간단한 응용은 행운의 쿠키 지급기다. 모듈을 메모리에 올린 다음에, 사용자는 echo 명령으로 행운의 메시지를 여러 개 올린 후 cat 명령으로 쿠키를 하나씩 읽을 수 있다.

Listing 9는 기본 모듈 함수와 변수를 나타낸다. init 함수(init_fortune_module)는 vmalloc으로 쿠키 단지를 위한 공간을 할당한 다음 memset으로 초기화한다. cookie_pot을 할당하고 비운 다음에는 proc_dir_entry로 /proc 루트에 fortune이라는 항목을 만든다. proc_entry를 성공리에 만들고 나면, 지역 변수와 proc_entry 구조체를 초기화한다. /proc readwrite 함수를 올리며(Listing 9와 Listing 10) 모듈 소유주를 파악한다. cleanup 함수는 단순히 /proc 파일 시스템에서 항목을 삭제하고 cookie_pot이 차지하던 메모리를 해제한다.

cookie_pot은 페이지 길이(4KB)이며, 색인 둘로 관리한다. 첫 번째 색인인 cookie_index는 다음에 쿠키를 쓸 위치를 가리킨다. 다음 색인인 next_fortune은 출력을 위해 다음에 읽을 쿠키 위치를 가리킨다. 모든 행운의 메시지를 읽은 다음에는 next_fortune을 한 바퀴 돌려 처음으로 설정한다.


Listing 9. 모듈 init/cleanup과 변수
        
#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/proc_fs.h>

#include <linux/string.h>

#include <linux/vmalloc.h>

#include <asm/uaccess.h>



MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Fortune Cookie Kernel Module");

MODULE_AUTHOR("M. Tim Jones");



#define MAX_COOKIE_LENGTH       PAGE_SIZE

static struct proc_dir_entry *proc_entry;



static char *cookie_pot;  // 행운의 문자열을 저장한 공간

static int cookie_index;  // 다음 행운의 문자열을 쓰기 위한 색인

static int next_fortune;  // 다음 행운의 문자열을 읽기 위한 색인





int init_fortune_module( void )

{

  int ret = 0;



  cookie_pot = (char *)vmalloc( MAX_COOKIE_LENGTH );



  if (!cookie_pot) {

    ret = -ENOMEM;

  } else {



    memset( cookie_pot, 0, MAX_COOKIE_LENGTH );



    proc_entry = create_proc_entry( "fortune", 0644, NULL );



    if (proc_entry == NULL) {



      ret = -ENOMEM;

      vfree(cookie_pot);

      printk(KERN_INFO "fortune: Couldn't create proc entry\n");



    } else {



      cookie_index = 0;

      next_fortune = 0;



      proc_entry->read_proc = fortune_read;

      proc_entry->write_proc = fortune_write;

      proc_entry->owner = THIS_MODULE;

      printk(KERN_INFO "fortune: Module loaded.\n");



    }



  }



  return ret;

}





void cleanup_fortune_module( void )

{

  remove_proc_entry("fortune", &proc_root);

  vfree(cookie_pot);

  printk(KERN_INFO "fortune: Module unloaded.\n");

}





module_init( init_fortune_module );

module_exit( cleanup_fortune_module );


새로운 쿠키를 단지에 담는 작업은 간단하다(Listing 10 참조). 기록될 쿠키 길이를 보고 저장 공간이 충분한지 확인한다. 그렇지 않다면 -ENOSPC를 넘겨 사용자 프로세스에 결과값을 돌려준다. 그렇지 않고 공간이 충분하다면, copy_from_user를 사용해 사용자 버퍼 내용을 직접 cookie_pot으로 복사한다. 그러고 나서 (사용자 버퍼 길이에 맞춰) cookie_index 값을 늘리고 NULL로 문자열 끝을 지정한다. 마지막으로 실제 cookie_pot에 기록한 문자 개수를 넘겨 사용자 프로세스로 결과값을 돌려준다.


Listing 10. 행운의 메시지를 쓰는 함수
        
ssize_t fortune_write( struct file *filp, const char __user *buff,

                        unsigned long len, void *data )

{

  int space_available = (MAX_COOKIE_LENGTH-cookie_index)+1;



  if (len > space_available) {



    printk(KERN_INFO "fortune: cookie pot is full!\n");

    return -ENOSPC;



  }



  if (copy_from_user( &cookie_pot[cookie_index], buff, len )) {

    return -EFAULT;

  }



  cookie_index += len;

  cookie_pot[cookie_index-1] = 0;



  return len;

}


행운의 메시지를 읽는 작업 역시 Listing 11처럼 단순하다. (page를) 기록할 버퍼가 이미 커널 영역에 존재하므로, 직접 접근해 sprintf로 다음 행운의 메시지를 기록한다. next_fortune 색인이 cookie_index보다 크다면(다음 쓰기 위치), next_fortune을 첫 행운의 메시지 위치 색인인 0으로 되돌린다. 행운의 메시지를 사용자 버퍼에 쓴 다음에, next_fortune 색인을 마지막 행운의 메시지 길이만큼 늘린다. 이는 다음 번에 넘길 행운의 메시지 색인을 표시한다. 버퍼에 쓴 행운의 메시지 길이를 반환해 사용자에게 전달한다.


Listing 11. 행운의 메시지를 읽는 함수
        
int fortune_read( char *page, char **start, off_t off,

                   int count, int *eof, void *data )

{

  int len;



  if (off > 0) {

    *eof = 1;

    return 0;

  }



  /* 한바퀴 돈다. */

  if (next_fortune >= cookie_index) next_fortune = 0;



  len = sprintf(page, "%s\n", &cookie_pot[next_fortune]);



  next_fortune += len;



  return len;

}


/proc 파일 시스템으로 커널과 통신하는 작업이 아주 간단하다는 사실을 이 예제를 통해 확인할 수 있다. 실제로 행운의 메시지를 쓰고 읽는 시연 과정을 살펴보자(Listing 12).


Listing 12. 행운의 쿠키 LKM 시연 모습
        
[root@plato]# insmod fortune.ko

[root@plato]# echo "Success is an individual proposition.  Thomas Watson" > /proc/fortune

[root@plato]# echo "If a man does his best, what else is there? 
              Gen. Patton" > /proc/fortune

[root@plato]# echo "Cats: All your base are belong to us.  Zero Wing" > /proc/fortune

[root@plato]# cat /proc/fortune

Success is an individual proposition.  Thomas Watson

[root@plato]# cat /proc/fortune

If a man does his best, what else is there?  Gen. Patton

[root@plato]#


/proc 가상 파일 시스템은 커널 정보 보고는 물론이고 동적 설정에 널리 쓰인다. 드라이버와 모듈 프로그래밍 모두에 적합한 기술이다. 아래 소개한 참고자료에서 더 많은 정보를 얻기 바란다.



참고자료

교육

제품 및 기술 얻기

토론


필자소개

M. Tim Jones 사진

M. Tim Jones는 임베디드 소프트웨어 아키텍트이자 GNU/Linux Application Programming, AI Application Programming, BSD Sockets Programming from a Multilanguage Perspective의 저자이기도 한다. Jones의 공학 배경은 정지 위성을 위한 커널 개발에서 시작해 임베디드 시스템 아키텍처와 네트워크 프로토콜 개발에 이르기까지 다양한 분야를 아우른다. Jones는 콜로라도 주, 롱몬트 소재 Emulex 사에서 컨설턴트 엔지니어로 활약한다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의