read, write함수에 관해


G711a , u coder and decoder 질록

/-
 * This source code is a product of Sun Microsystems, Inc. and is provided
 * for unrestricted use.  Users may copy or modify this source code without
 * charge.
 *
 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * Sun source code is provided with no support and without any obligation on
 * the part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
 * OR ANY PART THEREOF.
 *
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even if
 * Sun has been advised of the possibility of such damages.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 *-

/-
 * g711.c
 *
 * u-law, A-law and linear PCM conversions.
 *-
#define SIGN_BIT (0x80)  /- Sign bit for a A-law byte. *-
#define QUANT_MASK (0xf)  /- Quantization field mask. *-
#define NSEGS  (8)  /- Number of A-law segments. *-
#define SEG_SHIFT (4)  /- Left shift for segment number. *-
#define SEG_MASK (0x70)  /- Segment field mask. *-

static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
       0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};

/- copy from CCITT G.711 specifications *-
unsigned char _u2a[128] = {   /- u- to A-law conversions *-
 1, 1, 2, 2, 3, 3, 4, 4,
 5, 5, 6, 6, 7, 7, 8, 8,
 9, 10, 11, 12, 13, 14, 15, 16,
 17, 18, 19, 20, 21, 22, 23, 24,
 25, 27, 29, 31, 33, 34, 35, 36,
 37, 38, 39, 40, 41, 42, 43, 44,
 46, 48, 49, 50, 51, 52, 53, 54,
 55, 56, 57, 58, 59, 60, 61, 62,
 64, 65, 66, 67, 68, 69, 70, 71,
 72, 73, 74, 75, 76, 77, 78, 79,
 81, 82, 83, 84, 85, 86, 87, 88,
 89, 90, 91, 92, 93, 94, 95, 96,
 97, 98, 99, 100, 101, 102, 103, 104,
 105, 106, 107, 108, 109, 110, 111, 112,
 113, 114, 115, 116, 117, 118, 119, 120,
 121, 122, 123, 124, 125, 126, 127, 128};

unsigned char _a2u[128] = {   /- A- to u-law conversions *-
 1, 3, 5, 7, 9, 11, 13, 15,
 16, 17, 18, 19, 20, 21, 22, 23,
 24, 25, 26, 27, 28, 29, 30, 31,
 32, 32, 33, 33, 34, 34, 35, 35,
 36, 37, 38, 39, 40, 41, 42, 43,
 44, 45, 46, 47, 48, 48, 49, 49,
 50, 51, 52, 53, 54, 55, 56, 57,
 58, 59, 60, 61, 62, 63, 64, 64,
 65, 66, 67, 68, 69, 70, 71, 72,
 73, 74, 75, 76, 77, 78, 79, 79,
 80, 81, 82, 83, 84, 85, 86, 87,
 88, 89, 90, 91, 92, 93, 94, 95,
 96, 97, 98, 99, 100, 101, 102, 103,
 104, 105, 106, 107, 108, 109, 110, 111,
 112, 113, 114, 115, 116, 117, 118, 119,
 120, 121, 122, 123, 124, 125, 126, 127};

static int
search(
 int  val,
 short  *table,
 int  size)
{
 int  i;

 for (i = 0; i < size; i++) {
  if (val <= *table++)
   return (i);
 }
 return (size);
}

/-
 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
 *
 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
 *
 *  Linear Input Code Compressed Code
 * ------------------------ ---------------
 * 0000000wxyza   000wxyz
 * 0000001wxyza   001wxyz
 * 000001wxyzab   010wxyz
 * 00001wxyzabc   011wxyz
 * 0001wxyzabcd   100wxyz
 * 001wxyzabcde   101wxyz
 * 01wxyzabcdef   110wxyz
 * 1wxyzabcdefg   111wxyz
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 *-
unsigned char
linear2alaw(
 int  pcm_val) /- 2's complement (16-bit range) *-
{
 int  mask;
 int  seg;
 unsigned char aval;

 if (pcm_val >= 0) {
  mask = 0xD5;  /- sign (7th) bit = 1 *-
 } else {
  mask = 0x55;  /- sign bit = 0 *-
  pcm_val = -pcm_val - 8;
 }

 /- Convert the scaled magnitude to segment number. *-
 seg = search(pcm_val, seg_end, 8);

 /- Combine the sign, segment, and quantization bits. *-

 if (seg >= 8)  /- out of range, return maximum value. *-
  return (0x7F ^ mask);
 else {
  aval = seg << SEG_SHIFT;
  if (seg < 2)
   aval |= (pcm_val >> 4) & QUANT_MASK;
  else
   aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
  return (aval ^ mask);
 }
}

/-
 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
 *
 *-
int
alaw2linear(
 unsigned char a_val)
{
 int  t;
 int  seg;

 a_val ^= 0x55;

 t = (a_val & QUANT_MASK) << 4;
 seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
 switch (seg) {
 case 0:
  t += 8;
  break;
 case 1:
  t += 0x108;
  break;
 default:
  t += 0x108;
  t <<= seg - 1;
 }
 return ((a_val & SIGN_BIT) ? t : -t);
}

#define BIAS  (0x84)  /- Bias for linear code. *-

/-
 * linear2ulaw() - Convert a linear PCM value to u-law
 *
 * In order to simplify the encoding process, the original linear magnitude
 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
 * (33 - 8191). The result can be seen in the following encoding table:
 *
 * Biased Linear Input Code Compressed Code
 * ------------------------ ---------------
 * 00000001wxyza   000wxyz
 * 0000001wxyzab   001wxyz
 * 000001wxyzabc   010wxyz
 * 00001wxyzabcd   011wxyz
 * 0001wxyzabcde   100wxyz
 * 001wxyzabcdef   101wxyz
 * 01wxyzabcdefg   110wxyz
 * 1wxyzabcdefgh   111wxyz
 *
 * Each biased linear code has a leading 1 which identifies the segment
 * number. The value of the segment number is equal to 7 minus the number
 * of leading 0's. The quantization interval is directly available as the
 * four bits wxyz.  * The trailing bits (a - h) are ignored.
 *
 * Ordinarily the complement of the resulting code word is used for
 * transmission, and so the code word is complemented before it is returned.
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 *-
unsigned char
linear2ulaw(
 int  pcm_val) /- 2's complement (16-bit range) *-
{
 int  mask;
 int  seg;
 unsigned char uval;

 /- Get the sign and the magnitude of the value. *-
 if (pcm_val < 0) {
  pcm_val = BIAS - pcm_val;
  mask = 0x7F;
 } else {
  pcm_val += BIAS;
  mask = 0xFF;
 }

 /- Convert the scaled magnitude to segment number. *-
 seg = search(pcm_val, seg_end, 8);

 /-
  * Combine the sign, segment, quantization bits;
  * and complement the code word.
  *-
 if (seg >= 8)  /- out of range, return maximum value. *-
  return (0x7F ^ mask);
 else {
  uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
  return (uval ^ mask);
 }

}

/-
 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
 *
 * First, a biased linear code is derived from the code word. An unbiased
 * output can then be obtained by subtracting 33 from the biased code.
 *
 * Note that this function expects to be passed the complement of the
 * original code word. This is in keeping with ISDN conventions.
 *-
int
ulaw2linear(
 unsigned char u_val)
{
 int  t;

 /- Complement to obtain normal u-law value. *-
 u_val = ~u_val;

 /-
  * Extract and bias the quantization bits. Then
  * shift up by the segment number and subtract out the bias.
  *-
 t = ((u_val & QUANT_MASK) << 3) + BIAS;
 t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;

 return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}

/- A-law to u-law conversion *-
unsigned char
alaw2ulaw(
 unsigned char aval)
{
 aval &= 0xff;
 return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
     (0x7F ^ _a2u[aval ^ 0x55]));
}

/- u-law to A-law conversion *-
unsigned char
ulaw2alaw(
 unsigned char uval)
{
 uval &= 0xff;
 return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
     (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
}


리눅스 문제 분석과 해결 리눅스

가능하면 분석을 장황하게 쓸것없다.. 급할때 쓸수있는 유용한것들만 간추려 정리해놓자.
2장 strace
시스템호출을 살펴보자. 어셈블리 코드부터
move    $0x5, %eax
int        $0x80
바로위의 명령은 커널로 트랩을 걸어 IDT(interrupt descriptor table)내부의 0x80항목을 호출
나의 시스템의경우 아래와 같이 선언이 되어있다.
/linux-headers-2.6.35-27/arch/x86/include/asm/irq_vectors.h:50:
# define SYSCALL_VECTOR            0x80
IDT내부의 실제 0x80은 다음의 함수에서 설정함 set_system_gate(SYSCALL_VECTOR, &system_call);
IDT내부의 0x80항목을 커널진입점 system_call로 설정하고
system_call 은 entry.S에 정의 되어있다.
ENTRY(system_call)
...
call *SYSMBOL_NAME(sys_call_table)(,%eax,4)
//시스템 호출 테이블을 색인으로 참조, 이것이 시스템호출에 번호를 매기는이유

strace도구는 ptrace 라는 커널 인터페이스로 프로그램 동작 방식을 변경,
프로세스가 각 시스템 호출 진입점과 종료점에서 멈추도록 만들고 ptrace를 이용해
멈춘 프로세스에서 시스템 호출, 매개변수, 반환코드등의 정보를 획득
커널은 그저 프로세스를 멈추기만하고  부모프로세스에 중단되었음을 알린다.(이경우 strace 도구가 부모가됨)
정보를 얻는 작업은 strace도구에서 수행함

strace는 언제사용할까?초기 조사도구나 운영체제와 연관성이 있는 문제(예 : 파일을 열 수 없거나 메모리할당 실패)
ltace의 경우 함수단계에서 프로세스를 추적하나 동적링크가 필요함- 정적링크에서는 결과X,
또한 실행가능한 목적 파일내부에서 이뤄지는 자체적인 호출은 ltrace에 나타나지 않음

strace 사용예
gcc main.c -o main
strace -o main.strace main
cat main.strace

추적으로 나온 시스템 호출중 예를들어  execve 가 있다고하면
man 2 execve 로 확인 할 수 있다.
strace도구는 fork후 프로그램을 실행 exec계열의 함수는 새프로세스를 생성한다.
brk(0) = 0x8049f8  // 현재 정지점을 찾고 여기부터 프로세스 메모리 관리(malloc이나 free)를 시작함 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,0) = 0ㅌ40013000
//4KB짜리 빈(anonymous) 페이지를 생성
open("/etc/ld.so.preload", O_RDONLY)
//ld.so.preload파일을 열려고 시도, 이파일에는 프로그램을 실행하려면 먼저 올려야하는 ELF공유 라이브러리 목록이 들어있음-man ld.so
// 그다음행은 주로 라이브러리를 찾아서 올리는 과정이다.
LD_LIBRARY_PATH에 저장된 라이브러리 경로 순서에따라 프로세스초기화가 오래걸릴수도 있다.

그다음으로
mmap2()
mpprotect
mmap2(0x40128000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,3,0x113)=0x40128000
데이터 섹션 24576바이트를 메모리 주소 0ㅌ40128000에 올린다. 이주소는 메모리 세그먼트 시작주소인 0x40014000에서
0x114000바이트 떨어져 있다. libc.so.6의 ELF 헤더 정보에 따르면 데이터 섹션은 0x114920에서 시작하나, 섹션은 반드시
0x1000경계에서 정렬되어야 하므로 offset으로 0x114000을 사용 다음명령으로 확인할 수 있따.
readelf -l /lib/libc.so.6 
그다음 에는 공유라이브러리에서 사용하는 bss영역을 위한 영역 메모리 설정- 초기화되지 앟은 자료이므로 공유라이브러리 처럼
ELF객체에 포함 시킬 수가 없다. 주목할 점은 bss 섹션 중 일부인 0x740바이트는 데이터 섹션의 마지막 페이지에 위치한다.
시스템 단계에서 메모리를 다룰 때는 최소단위가 항상 페이지 크기이며 IA-32플랫폼에서 기본페이지 크기는 0x1000바이트이다.
bss섹션의 offset은 0x001198c0으로 페이지 경계에 있지않다. 그래서 다음 페이지 경계인 0x4012e000에 나머지
bss세그먼트용 메모리를 할당 한다. bss 섹션크기가 0x4100이고 이중 0x740 바이트는 데이터 섹션의 마지막 페이지에 포함
되므로, 나머지 bss세그먼트인 0x39C0(십진수로 14784)바이트만큼을 0x4012e000에서 할당 한다.
그다음 libc파일기술자를 닫고, 실제 프로그램 코드에서 호출하는 유일한 시스템호출을 한다. 대충이런식

동일한 예제를 정적으로 빌드한 경우

주요 옵션과 시용시점
기본적으로 자식프로세스는 추적하지 않지만, 자식프로세스까지 모두 추적해야할 경우도 있다.
- 명령행 셸의 활동을 추적하는 경우
- 추적 중인 프로세스가 데몬 프로세스를 생성시켜, 명령행 도구가 종료한 후에도 데몬 프로세스가 계속 실행되는 경우
- inetd 또는 xinetd를 추적하여 시스템 로그인 문제나 원격 연결 문제를 조사하는 경우
- 추적 중인 프로세스가 작업자 프로세스를 생성시켜, 실제 작업은 작업자 프로세스가 수행하고 부모 프로세스는 작업자 프로세스
 풀을 관리하는 경우
-f : 부모자식 모두 추적 (fork로생성할 경우만) -> 포크이후 결과출력에 프로세스ID가 붙고 이것으로 구분하면됨,
항상 사용하는 편이 좋다.

시스템 호출 활동 시간 측정 - 프로세스가 시간을 소비하는 병목 지점을 파악할 수 있는 정보를 제공함
-t : 의 경우 strace출력에 타임스탬프를 추가하는데, 두 타임스탬프 값의 차이는 첫번째 시스템 호출을 수행한 시간과
두번째 시스템 호출 직전까지 사용자 코드를 실행한 시간임,, 
-tt :타임스탬프를 얻으려할 때  가장편함, 하루 중 시각을 마이크로초로 출력
-r : 시스템 호출사이의 시간.. 시스템호출에 걸린 시간과 사용자코드를 실행한 시간을 모두포함 대체로 이값은 실용성이 떨어짐
-T or -C: 실제 시스템 호출에 걸린 시간
시스템 호출 항목사이에 흘러간 시간과 시스템 호출에 걸린 시간의 차이는 호출사이의 사용자코드에서 보낸시간을 얻을 수 있다.
또한 strace 출력을 분석하려면 간단한 스크립트를 작성해야함
참고 : 일부 시간 소모는 싀스템 호출이나 사용자 코드 탓이 아니라 시스템의 스케줄링 방식 때문일 수도 있다. 바쁜 시스템에서는
서로 다른 프로그램이 CPU시간을 놓고 경쟁을 벌이므로 해당 프로그램이 잠깐 동안 실행되지 못할 수도 있다.

-v :상세 출력 모드, 문제 진단위해 더많은 정보가 필요한 상황 stat 이나 uname등과 같은 시스템호출에 대한 모든 정보 표시
-s : 상세 출력 모드, read와 write에서 더 자세한 정보를 제공, 특정값을 담은 문자열의 최대 크기를 설정 할 수있다.
-s 256  이런식으로

실행중인 프로세스 추적 - 때로 웹데몬(아파치등)이나 xinetd같이 실행중인 프로세스를 추적해야할 경우가 있는데
-p : 실행중인 프로세스에 strace도구를 붙임 strace -p 3423

strace 영향과 고려 사항
심하진 않으나 프로그램 실행과정에 영향을 미침 - 추적되는 프로세스의 성능을 저하시킴
pause() 함수에서 대기하느라 수면 중인 프로세스를 깨울 때도 있다.
strace도구는 출력을 stderr로 보내므로, 추적되는 프로세스의 출력과 strace의 출력을 분리하기가 쉽다.
예로 csh나 tcsh에서 (strace /bin/ls > /dev/null) | & less  명령으로 실제로 추적한 strace 결과만 볼 수 있음
하지만 대개 -o 옵션으로 strace 결과를 파일로 보내는 방법이 더편하다.
setuid root 프로그램을 명령행에서 추적하는경우, strace프로그램을 돌리는 사용자가 setuid root 프로그램을
실행하는 셈이므로 일반 사용자가 setuid root 프로그램의 정상적인 동작을 추적하기 어렵다.
이미 실행중인 setuid root 프로그램이 유효사용자 ID를 실제 사용자ID로 변경한다 해도, strace에 프로세스를 붙여
추적할 수는 없다. 프로세스가 root로 실행되던 당시에 사용하던 주요 정보가 메모리에 여전히 남아 있을지도 모르는
보안문제 때문이다.
setuid root 프로그램을 추적하는 방법
1. root로 strace를 실행해서 setuid root 프로그램을 추적
2. -f 옵션으로 root로 셀을 추적해 setuid root 프로그램을 수행시켜 따라감

strace 와 EINTR
인터럽트가 걸린 시스템 호출을 올바로 처리하지 못하는 프로그램을 strace로 추적할 경우,
대상 프로그램에 문제가 생길확률이 매우 높다. 다음을 보자.
result = accept(s, addr, &addrlen);
if( result < 0 ){
    perror("accept");
    return(SOCKET) INVALID_SOCKET;
} else
    return result;
위 함수는 accept() 호출에 걸리는 인터럽트를 올바로 처리하지 못하므로 strace로 추적하기 노안전
프로세스가 accept()에서 대기하는 도중에 strace를 붙인다면, 프로세스는 accept()호출을 빠져나와 perror()
시스템 호출에 인터럽트가 걸렸을 때 반환되는 오류 코드(errno)는 EINTR이다. 위코드에서는 EINTR 오류 코드를
처리하지 않으므로, 프로세스는 제대로 복구하지 못하고, 심지어는 그대로 종료해 버릴 지도 모름
코드를 다음과 같이 바꾸자.
do
{
  result = accept(s, addr, &addrlen);
} wihle ( result < 0 && errno == EINTR );
if( result < 0 ){
    perror("accept");
    return(SOCKET) INVALID_SOCKET;
} else
    return result;

디버깅 실례
LD_LIBRARY_PATH환경변수는 런터임 링커가 실행 파일이나 라이브러리를 위한 의존 라이브러리를
찾을 때 사용한다. ldd명령으로 의존 라이브러리를 확인할 수 있다.
ldd /bin/ls
경로를 수정해서 좀더 효율적으로 찾기를 수행시킬 수 있다.(특히 스크립트나 CGI프로그램)














pcap library 질록

데스크탑환경에(우분투 10.10) 설치
sudo apt-get install libpcap0.8-dev
넷상황이 안좋아서 놋북의 패키지파일을 찾아서 복사해와서 설치했다.
sudo dpkg -i package.deb

큰 파일 분할 리눅스

큰 용량의 파일 분할하기

 

예) split -b [size] [백업파일명] [백업구분자] 

----------------------------------------------------------------
[guest@locahost ~]$ split -b 650m - bigsize.tgz small_


bigsize.tgz 파일을 small_aa, small_ab, small_ac 형식으로 생성한다.

 

 

나눠진 파일합치기

 

[guest@locahost ~]$ cat small_aa small_ab small_ac > bigsize.tgz

나뉘어진 small_aa small_ab등의 파일을 bigsize.tgz의 하나의 파일로 생성한다.

 


용량이 큰 디렉토리를 특정 사이즈의 파일로 나눠 압축하기



/home/test 디렉토리를 200MB 단위로 backupfile_xx 형태로 압축을 한다면

 

[guest@locahost ~]$ tar cvfz | split -b 200m - backupfile.tar.gz_

 

압축된 파일의 해제는

 

[guest@locahost ~]$ cat backupfile.tar.gz_* | tar xvfz -

 

만약 tar에서 gzip을 지원하지 않는 경우는 다음과 같이 하면 된다.

 

[guest@locahost ~]$ tar cvfp - test/ | gzip - | split -b 700m - test.tar.gz

[guest@locahost ~]$ cat tst.tar.gz* | gzip -d - | tar xvfp -


1 2