<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>!엔죠라이프 블로그 &#187; Linux</title>
	<atom:link href="http://www.esll.net/blog/tag/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.esll.net/blog</link>
	<description>Life is beautiful</description>
	<lastBuildDate>Sun, 01 Jan 2012 06:56:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>왜 리눅스 커널을 알아야 하는가?</title>
		<link>http://www.esll.net/blog/2007/05/%ec%99%9c-%eb%a6%ac%eb%88%85%ec%8a%a4-%ec%bb%a4%eb%84%90%ec%9d%84-%ec%95%8c%ec%95%84%ec%95%bc-%ed%95%98%eb%8a%94%ea%b0%80/</link>
		<comments>http://www.esll.net/blog/2007/05/%ec%99%9c-%eb%a6%ac%eb%88%85%ec%8a%a4-%ec%bb%a4%eb%84%90%ec%9d%84-%ec%95%8c%ec%95%84%ec%95%bc-%ed%95%98%eb%8a%94%ea%b0%80/#comments</comments>
		<pubDate>Fri, 04 May 2007 11:00:23 +0000</pubDate>
		<dc:creator>!엔죠라이프</dc:creator>
				<category><![CDATA[잡동사니/IT일반, 서버]]></category>
		<category><![CDATA[EMBED]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[SYSTEM]]></category>
		<category><![CDATA[리눅스]]></category>
		<category><![CDATA[임베디드]]></category>
		<category><![CDATA[커널]]></category>

		<guid isPermaLink="false">http://www.esll.net/blog/2007/05/%ec%99%9c-%eb%a6%ac%eb%88%85%ec%8a%a4-%ec%bb%a4%eb%84%90%ec%9d%84-%ec%95%8c%ec%95%84%ec%95%bc-%ed%95%98%eb%8a%94%ea%b0%80/</guid>
		<description><![CDATA[저자: 서민우 일반적으로 리눅스를 이용한 임베디드 시스템의 개발은 다음과 같은 순서로 진행된다. 1) 특정한 용도에 맞추어진 임베디드 하드웨어 설계 및 제작2) 해당 임베디드 하드웨어에 리눅스 커널 포팅3) 특정한 용도에 맞는 디바이스 드라이버의 개발4) 이러한 디바이스를 접근해 적당한 작업을 수행할 응용프로그램 개발 특정한 디바이스를 접근하기 위해 작성한 디바이스 드라이버는 전 단계에서 포팅한 리눅스 커널의 일부가 된다. [...]]]></description>
			<content:encoded><![CDATA[<p>저자: 서민우</p>
<p>일반적으로 리눅스를 이용한 임베디드 시스템의 개발은 다음과 같은 순서로 진행된다.</p>
<p>1) 특정한 용도에 맞추어진 임베디드 하드웨어 설계 및 제작<br />2) 해당 임베디드 하드웨어에 리눅스 커널 포팅<br />3) 특정한 용도에 맞는 디바이스 드라이버의 개발<br />4) 이러한 디바이스를 접근해 적당한 작업을 수행할 응용프로그램 개발</p>
<p>특정한 디바이스를 접근하기 위해 작성한 디바이스 드라이버는 전 단계에서 포팅한 리눅스 커널의 일부가 된다. 따라서 우리는 우리가 작성한 디바이스 드라이버가 리눅스 커널에 어떻게 끼워지는지, 끼워진 후 어떤 흐름에 의해 동작을 하는지 알아야 한다. </p>
<p>일반적으로 리눅스 커널의 포팅은 커널의 내용을 자세히 몰라도 가능하지만 디바이스 드라이버의 개발은 포팅과는 전혀 다른 방향에서 접근해야 한다. 즉, 리눅스 커널의 흐름을 정확히 알아야 디바이스 드라이버의 정확한 개발이 가능하다.</p>
<p>리눅스 커널의 주요한 두 흐름</p>
<p>일반적으로 리눅스 커널로의 진입은 hardware interrupt 와 system call 에 의해서이다. 따라서 hardware interrupt 에 의해 수행되는 routine 과 system call 에 의해 수행되는 routine 의 구조와 흐름의 파악이 커널을 이해하는데 꼭 필요하다. 즉, 우리는 hardware interrupt routine 과 system call routine 을 이해함으로써 리눅스 커널의 대부분을 이해할 수 있다.</p>
<p>hardware interrupt routine</p>
<p>hardware interrupt routine 은 디바이스 컨트롤러 &#8211; 예를 들어 이더넷 카드의 제어칩이나 하드디스크의 제어칩 &#8211; 의 물리적인 신호에 의해서 시작되는 routine 이다. 그렇다면 이러한 신호는 왜 필요한가? </p>
<p>디바이스 컨트롤러는 이 신호를 이용해 밖에서 오는 데이터의 도착이나 밖으로 나갈 데이터를 모두 보냈음을 알린다. </p>
<p>예를 들어, 이더넷의 경우 밖에서 오는 데이터가 랜선을 통해 컨트롤러 안의 특정한 데이터 저장 영역에 도착하게 된다. 데이터가 정상적으로 도착할 경우 컨트롤러는 물리적인 인터럽트 신호를 통해서 CPU 에 데이터의 도착을 알린다. CPU 의 다음 동작은 칩내에 도착해 있는 데이터를 메모리로 읽어 가는 것이어야 한다. 이러한 CPU 의 동작을 제어하는 루틴이 바로 인터럽트 핸들러의 한 부분이다.</p>
<p>이더넷을 통해 밖으로 데이터를 내보낼 경우도 보자. 먼저 CPU 에 의해 메모리로부터 컨트롤러의 데이터 저장영역으로 데이터가 쓰여져야 하고, 다음으로 컨트롤러는 이 데이터를 랜선을 통해서 밖으로 내 보내야 한다. 컨트롤러가 랜선을 통해 데이터를 내 보내고 있는 동안에는 컨트롤러의 데이터 저장영역은 사용할 수가 없다. 컨트롤러는 데이터 저장영역에 있는 데이터를 밖으로 모두 내보내고 나면 인터럽트를 통해서 CPU 에 데이터 저장영역을 또 쓸 수 있음을 알린다.</p>
<p>지금까지 우리는 인터럽트의 필요성과 그에 따른 CPU 의 동작을 보았다. </p>
<p>이상에서 hardware interrupt routine 의 주요한 내용은 디바이스를 접근해서 도착한 데이터를 읽어오거나 또는 디바이스에 새로운 데이터를 쓰는 것이다.</p>
<p>다음으로 hardware interrupt routine 의 구체적인 동작을 들여다 보자.</p>
<p>새로 도착한 데이터의 경우 일단은 디바이스로부터 메모리로 데이터를 읽어오는 동작이 있어야 하고, 다음으로 메모리로 읽어온 데이터를 적당한 프로세스에게 전달해 주어야 한다. 리눅스에서 앞의 동작을 보통 인터럽트 핸들러의 top half 라 하고 뒤의 동작을 bottom half 라 한다. </p>
<p>굳이 이렇게 인터럽트 핸들러를 두 부분으로 나눈 이유는 다음과 같다. top 부분에서는 신속하게 디바이스를 접근함으로써 디바이스가 빠른 시간 내에 다시 데이터를 받거나 하는 동작을 수행하게 한다. 보통 이 부분에서는 또 다른 인터럽트를 허용하지 않음으로써 이를 가능하게 한다. bottom half 에서는 인터럽트를 열어놓음으로써 또 다른 인터럽트에 대한 응답성을 좋게 한다. 즉, top half 에서는 디바이스에서 데이터를 읽어오는 작업을 하며, bottom half 에서는 읽어온 데이터를 적절히 처리해 적당한 process 에게 전달을 한다.</p>
<p>리눅스에서 hardware interrupt routine 의 일반적인 흐름은 다음과 같다.
<div style="text-align: center; clear: both;" class="imageblock center"><img src="http://www.esll.net/blog/wp-content/uploads/1/1036972777.gif" width="509" height="411" alt="User inserted image" /></div>
<p>그림에서 CPU 가 process 영역 수행 중에 hardware interrupt 가 발생하면 CPU 는 hardware interrupt routine 으로 뛰어 들어간다. interrupt routine 내에서 routine 전후에 process 영역의 문맥을 저장하고 복구한다. do_IRQ 함수 내에 top half 와 bottom half routine 이 모두 포함되며 이 부분에서 인터럽트에 대한 처리를 한다. </p>
<p>timer interrupt 에 의해 interrupt routine 이 수행될 경우 현재 process 의 time slice 가 0 이 될 수 있으며, 이 경우 schedule 함수에서 새로운 process 를 선택해서 그 process 로 작업이 전환될 수도 있다.</p>
<p>do_signal 함수에서는 현재 process 에게 전달된 signal 이 있는지 확인하여 있을 경우에는 signal handler 를 수행한다.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>리눅스 커널 2.6의 주요 구조와 응용 세미나</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>system call routine</p>
<p>다음은 system call routine 을 보자. </p>
<p>system call routine 은 process 에 의해 시작되는 routine 이다. i386 계열의 CPU 의 경우 int(interrupt 의 약자) 란 명령어, arm 의 경우 swi(software interrupt 의 약자) 란 명령어, mips 의 경우 syscall(system call 의 약자) 이란 명령어 등을 사용한다. 즉, process 에 의해 진입하는 커널루틴을 system call routine 내지는 software interrupt routine 이라고 한다.</p>
<p>이러한 system call 은 process 에서 커널을 접근하는 방법인데 그렇다면 왜 이러한 system call 이 필요한가?</p>
<p>process 는 system call 을 통해서 process 영역의 데이터를 커널로 내려 보내기를 요청하거나 또는 커널의 데이터를 process 영역으로 가져오기를 요청한다. 즉, 디바이스가 인터럽트를 통해서 CPU 가 디바이스로부터 데이터를 읽어 가거나 디바이스에 데이터를 쓰기를 요청하듯이 process 는 system call 을 통해서 커널에서 process 의 데이터를 읽어가거나 process 영역으로 데이터를 써 주기를 요청한다. 다음의 예를 보자.</p>
<p>네트워크 통신을 하는 process 의 경우 일반적으로 socket 을 생성해서 그 socket 에 데이터를 쓰거나 읽기를 반복한 후 그 socket 을 닫음으로써 통신을 마친다. socket 에 데이터를 쓰고자 할 경우 process 는 쓰고자 하는 데이터를 만든 후 write 등의 system call 함수를 통해 커널영역으로 데이터를 보낸다. 커널영역에서는 이 데이터를 적당히 가공한 후에 디바이스 컨트롤러로 쓴 후에 process 영역으로 리턴한다. 또 socket 으로부터 데이터를 읽고자 할 경우 process 는 read 등의 system call 함수를 통해 커널로부터 데이터를 읽기를 요청한다. 커널영역에서는 이 프로세스의 socket 을 접근해서 도착한 데이터 &#8211; 이 데이터는 hardware interrupt routine 의 bottom half 에 의해서 전달된다 &#8211; 가 있는지를 본 후 있으면 socket 으로부터 데이터를 process 영역으로 읽어준 후 process 영역으로 리턴 한다. socket 에 도착한 데이터가 없을 경우 현재 process 의 진행을 임시 중단한 후 스케쥴링을 통해 다른 process 를 수행한다. 흔히 말하는 sleep 이니 wait 니 blocking 이니 하는 용어는 이러한 상황에서 쓰인다.</p>
<p>물론 process 는 system call 을 통해서 이외에도 다른 여러 가지 작업을 커널에 요청한다.</p>
<p>System call routine 의 일반적인 흐름은 다음과 같다
<div style="text-align: center; clear: both;" class="imageblock center"><img src="http://www.esll.net/blog/wp-content/uploads/1/1343577556.gif" width="501" height="413" alt="User inserted image" /></div>
<p>현재 process 의 swi 등의 명령어에 의해 수행되는 system call routine 은 다른 부분은 hardware interrupt routine 과 같으나 sys_func 함수 호출하는 부분이 다르다. 이 부분에서 커널영역의 여러 데이터를 건드릴 수 있다. 중간에 두 개의 줄 사이에서 interrupt 를 허용한다. 따라서 이 부분에서 interrupt routine 이 겹칠 수 있다. 이 부분에 대해서는 추후에 좀 더 다루고자 한다.</p>
<p>두 루틴간의 상호 작용</p>
<p>다음 그림을 보자.
<div style="text-align: center; clear: both;" class="imageblock center"><img src="http://www.esll.net/blog/wp-content/uploads/1/1218984356.gif" width="600" height="229" alt="User inserted image" /></div>
<p>이 그림의 왼쪽은 hardware interrupt routine 이며 오른쪽은 software interrupt routine 이다. 이처럼 두 루틴은 일반적으로 중간에 공유버퍼를 두고 데이터를 주고 받는다. 그리고 우리가 작성할 디바이스 드라이버는 이 두 루틴에 모두 포함된다.</p>
<p>마무리</p>
<p>이상에서 우리는 hardware interrupt routine 과 system call routine 의 일반적인 동작을 보았다. 이 두 routine 에는 디바이스를 접근하는 routine 이 포함되며, 이러한 디바이스를 접근하는 routine 을 우리는 device driver 라고 한다. 우리가 작성하는 device driver 는 hardware interrupt routine 과 system call routine 에 모두 포함된다. 즉, 커널의 일부가 되어 해당 디바이스를 접근한다. 따라서 이 두 routine 의 흐름을 알지 않고서, 즉 커널의 흐름을 알지 않고서 거기에 끼워 넣어질 device driver 를 제대로 작성하기란 불가능하다. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.esll.net/blog/2007/05/%ec%99%9c-%eb%a6%ac%eb%88%85%ec%8a%a4-%ec%bb%a4%eb%84%90%ec%9d%84-%ec%95%8c%ec%95%84%ec%95%bc-%ed%95%98%eb%8a%94%ea%b0%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

