
'분류 전체보기'에 해당되는 글 73건
- 2008.06.02
- 2008.06.02
- 2008.05.29
- 2008.05.29
- 2008.05.29
-
2008.05.26
fork 설명 2
- 2008.05.22
- 2008.05.21
- 2008.05.21
- 2008.05.21
우선 예재 프로그램을 대충 만들어 보겠습니다.
각 section은 어떤 특정한 일을 하는 부분이고, pid, pid2는 미리 선언했다고 가정합시다.
// section A
pid = fork();
if (pid != 0) {
// section B
}
else {
// section C
pid2 = fork();
if (pid2 != 0) {
// section D
}
else {
// section E
}
// section F
}
section G
자.. 이제 이 프로그램을 컴파일해서 실행파일을 만들구요...
실행 파일을 실행 시키면 우선 첫 프로세스가 뜨겠죠? 이놈을 P1이라고 부릅시다.
P1은 프로그램이 짜여진대로 section A를 실행하고 pid = fork()문을 만납니다.
그리고 fork()를 실행하지요... 그러면 새로운 프로세스가 만들어지는데 P2라고 부릅시다.
P2는 P1의 환경을 그대로 가져옵니다. 즉, 지금 프로그램이 어디까지 실행되었는가라는
정보까지 그대로 가져오지요.. 그래서 P1도 P2도 모두 fork())이후의 pid = (fork()의 return 값)
pid에 대입하는 부분부터 실행합니다.
자.. 문제는 P1은 fork로부터 P2의 프로세스 ID를 받습니다.
새로 프로세스가 만들어졌으니 당연히 프로세스 ID가 있겠죠?
P2는 자기가 새로 만들어진 놈이므로 그냥 0을 return 받습니다.
따라서 똑같은 부분부터 시작은 하되.... fork()의 return값은 다른 놈을 가지고 P1, P2가 실행됩니다.
이 때, 우리는 주로 P1을 부모, P2를 자식이라고 설명합니다.
바로 다음 if문에 의해서
P1은 section B를 실행하게 되고 P2는 section C를 실행하게 됩니다.
return 받은 pid가 다르니까 if의 조건이 달라지죠?
P1은 section B를 실행한 후에 당연히 section G를 실행하고 끝납니다.
P2는 section C를 실행하고 다시 fork()를 만납니다.
fork를 실행하면 아시다시피 fork를 호출한 프로세스와 똑같은 프로세스가 하나 더
만들어 집니다.
즉 P2와 똑같은 놈 P3가 만들어지고 fork()로 부터 return을
P2는 P3의 프로세스 ID를 받고
P3는 자신이 fork되었으니 0을 받습니다.
그리고는 똑같은 위치인 pid2 = (fork의 return값) 을 실행합니다.
이때는 P2가 부모이고 P3가 자식이죠?
P2는 section D, F, G를 차례로 수행하고 끝날테구요..
P3는 section E,F,G를 수행하고 끝납니다.
여기서 주의할 점은 각 프로세스가 어느 놈이 먼저 수행될지는 아무도 모른다는 것이고,
이를 위해서 동기화 방법들이 있는 것입니다.
암호학에서 MD5(Message-Digest algorithm 5)는 128비트 해시를 제공하는 암호화 해시 함수이다. RFC 1321로 지정되어 있으며 수많은 프로그램과 파일의 무결성 검사에 사용된다.
MD5는 1991년에 로널드 라이베스트가 예전에 쓰이던 MD4를 대체하기 위해 고안했다. 1996년에는 MD5의 설계상 결함이 발견되었다. 매우 치명적인 결함은 아니었지만, 암호학자들은 SHA-1 같은 다른 알고리즘을 사용할 것을 권장하기 시작했다. 2004년에는 더욱 심한 암호화 결함[1]이 발견되었고 2006년에는 노트북 컴퓨터 한 대의 계산 능력으로 1분 내에 해시 충돌을 찾을 정도로 빠른 알고리즘이 발표[2]되기도 하였다. 사람들은 MD5 알고리즘을 보안 관련 용도로 쓰는 것을 그다지 권장하지 않는다.
〈〈〉〉== 알고리즘 ==
MD5는 임의의 길이의 메시지(variable-length message)를 입력받아, 128비트 짜리 고정 길이의 출력값을 낸다. 입력 메시지는 512 비트 블록들로 쪼개진다; 메시지를 우선 패딩하어 512로 나누어 떨어질 수 있는 길이가 되게 한다. 패딩은 다음과 같이 한다: 우선 첫 단일 비트, 1을 메시지 끝부분에 추가한다. 512의 배수의 길이보다 64 비트가 적은 곳까지 0으로 채운다. 나머지 64 비트는 최초의(오리지널) 메시지의 길이를 나타내는 64 비트 정수(integer)값으로 채워진다.
메인 MD5 알고리즘은 A,B,C,D라고 이름이 붙은 32 비트 워드 네 개로 이루어진 하나의 128 비트 스테이트(state)에 대해 동작한다. A,B,C,D는 소정의 상수값으로 초기화된다. 메인 MD5 알고리즘은 각각의 512 비트 짜리 입력 메시지 블록에 대해 차례로 동작한다. 각 512 비트 입력 메시지 블록을 처리하고 나면 128 비트 스테이트(state)의 값이 변하게 된다.
하나의 메시지 블록을 처리하는 것은 4 단계로 나뉜다. 한 단계를 "라운드"(round)라고 부른다; 각 라운드는 비선형 함수 F, 모듈라 덧셈, 레프트 로테이션(left rotation)에 기반한 16개의 동일 연산(similar operations)으로 이루어져 있다. 오른쪽 "그림 1"은 한 라운드에서 이루어지는 한 연산(operation)을 묘사하고 있다.
함수 F에는 4가지가 있다; 각 라운드마다 각각 다른 F가 쓰인다:
는 각각 XOR, 논리곱, 논리합 그리고 NOT 연산을 의미한다.
MD5 알고리즘의 슈도코드는 다음과 같다:
//Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating var int[64] r, k //r specifies the per-round shift amounts r[ 0..15] := {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22} r[16..31] := {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20} r[32..47] := {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23} r[48..63] := {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21} //Use binary integer part of the sines of integers as constants: for i from 0 to 63 k[i] := floor(abs(sin(i + 1)) × (2 pow 32)) //Initialize variables: var int h0 := 0x67452301 var int h1 := 0xEFCDAB89 var int h2 := 0x98BADCFE var int h3 := 0x10325476 //Pre-processing: append "1" bit to message append "0" bits until message length in bits ≡ 448 (mod 512) append bit (bit, not byte) length of unpadded message as 64-bit little-endian integer to message //Process the message in successive 512-bit chunks: for each 512-bit chunk of message break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15 //Initialize hash value for this chunk: var int a := h0 var int b := h1 var int c := h2 var int d := h3 //Main loop: for i from 0 to 63 if 0 ≤ i ≤ 15 then f := (b and c) or ((not b) and d) g := i else if 16 ≤ i ≤ 31 f := (d and b) or ((not d) and c) g := (5×i + 1) mod 16 else if 32 ≤ i ≤ 47 f := b xor c xor d g := (3×i + 5) mod 16 else if 48 ≤ i ≤ 63 f := c xor (b or (not d)) g := (7×i) mod 16 temp := d d := c c := b b := b + leftrotate((a + f + k[i] + w[g]) , r[i]) a := temp //Add this chunk's hash to result so far: h0 := h0 + a h1 := h1 + b h2 := h2 + c h3 := h3 + d var int digest := h0 append h1 append h2 append h3 //(expressed as little-endian)
//leftrotate function definition
leftrotate (x, c)
return (x << c) or (x >> (32-c));
주석: RFC 1321에 나온 공식 말고 다음과 같은 공식이 쓰일 수 있다. 다음과 같은 공식을 쓰면 퍼포먼스가 향상될 수 있다. (어셈블리 언어가 사용될 때 유용하다 - 다른 언어가 쓰일 경우에는 대개 컴파일러가 위의 코드를 최적화 해준다.):
(0 ≤ i ≤ 15): f := d xor (b and (c xor d)) (16 ≤ i ≤ 31): f := c xor (d and (b xor c))
네트웍에서 Nagle 알고리즘은 "가능하면 조금씩 여러번 보내지말고 한번에 많이 보내라(Effective TCP)" 라는 원칙을 기반으로 만들어진 알고리즘입니다.
WinSock 의경우 기본으로 Navle 알고리즘이 적용이 되어있습니다. 하지만 몇몇 네트웍 관련 프로그램에서는 네트웍 의 전송량이나 부하보다는 빠른 응답속도를 더 중요시 여기는 상황이 있습니다. 그러한때에는 TCP_NODELAY 라는 옵션을 사용하여 Nagle 알고리즘을 제거 할 수 있습니다.
해당 코드를 적용하는 방법은
int nValue = 1;
setsockopt( TCP_NODELAY, &nValue, sizeof(int), IPPROTO_TCP );
의 코드를 사용합니다.
아래는 100Byte 의 패킷을 5번에 걸처서 보내고 에코로 받은 결과입니다.
Nagle 알고리즘 적용 (default) : 100~150ms
Nagle 알고리즘 해제 : 1~3 ms
하지만 해당 옵션의 사용은 네트웍 부하를 극대화 시켜주면서 서버의 전체적인 성능을
무척감소하기때문에 꼭 필요한경우에만 매우 주의를 해서 사용해야 합니다.
추가로 "Effective TCP Programming" 역시 추천도서입니다. ^^
네트웍 프로그램을 향상하는 44가지 팁이라고 하는데 저의 경우
15개정도의 팁만이 쓸모가 있더군요.
[디스크 Quota]
다중 사용자를 환경으로 하는 Linux 환경에서 특정 사용자가 시스템의 모든 디스크를 독점하여 사용하게 된다면 큰일이다.
한 사용자에 의해서 독점되는 시스템 자원으로 인해서 다른 사용자는 하고자 하는 작업을 할 수가 없게 된다.
특히, 웹 호스팅을 하는 업체와 같은 경우에는 사용자에게 일정한 디스크 용량만을 사용할 수 있게 하는 기능이 필수적이라고 할 수 있다.
웹 호스팅을 하는 서버의 경우 보통 적게는 100명 많게는 200명의 사용자가 홈페이지를 운영하고 있기 때문에 제한된 자원을 모든 사용자가 사용할 수 있도록 해주어야 한다.
이러한 요구 사항을 충족하기 위해서 사용하는 기능이 디스크 Quota 기능이다. 쿼터 기능을 사용해서 관리자는 사용자마다 일정한 디스크 용량만을 사용할 수 있도록 할 수 있기 때문에 효율적으로 하드 디스크 공간을 사용할 수 있다.
그러면 Quota 기능을 어떻게 설정하고 사용하는지에 대해서 알아보도록 하자.
[ TIP : ]
Window NT 4.0의 경우에는 이 Quota 기능이 없어서 사실상 웹 호스팅을 하거나 많은 사람에게 디스크를 사용하게 한다는 것은 거의 불가능한 일이었다.
필자의 경우는 여러 사람에게 디스크 공간을 한정되게 주기 위해서 파티션을 나누어서 제공한 적이 있다.
그러나 윈도우 2000부터는 쿼터 기능이 지원되기 때문에 요즈음 윈도우 2000과 ASP를 사용해서 웹 호스팅을 하는 업체가 부쩍 늘고 있다.
[출처] 리눅스 공부 - 디스크 Quota|작성자 길당