블로그 이미지
progh2
지루한 것에서 벗어나 재미난 것 속으로 풍덩~☆

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

Recent Post

Recent Comment

Archive

'기술문서창고/리눅스 프로그래밍'에 해당되는 글 15

  1. 2004.07.18 쉘 프로그래밍 - 리스트
  2. 2004.07.18 쉘 - 변수, 조건, 비교, 제어
  3. 2004.07.18 제2장 쉘 프로그래밍 - 츌력 재지정, 권한주기
  4. 2004.07.18 유닉스의 철학
  5. 2004.07.18 공유 라이브러리와 ldd
  6. 2004.07.18 정적 라이브러리와 ar, ranlib, nm
  7. 2004.07.18 제1장 시작하기
리스트
and 리스트 구조 - 이전의 모든 명령이 성공적이었다면 다음 명령을 실행하며 일련의 명령을 실행하게 해준다.
statement1 && statement2 && ...
각 문장은 왼쪽에서부터 실행되고, 이것이 true를 반환하면 오른쪽 다음 문장이 실행도니다. 이런 과정이 false를 반환할 때까지 계속된다. &&는 이전 명령의 조건을 테스트한다.

or 리스트 구조 - 하나의 명령이 성공할 때까지 일련의 명령을 실행
statement1 || statement2 || ...
각 문장은 왼쪽에서부터 실행되며 false를 반환하면 오른쪽의 문장이 실행, true를 반환할 때까지 계속되며 true를 반환하면 멈추게 된다.
[CODE]#!/bin/sh # and list touch file_one rm -f file_two if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there" then echo "in if" else echo "in else" fi # or list rm -f file_one if [ -f file_one ] || echo "hello" || echo " there" ; then echo "in if" else echo "in else" fi exit 0[/CODE]
or 리스트 구조에서 결과를 결정하기 위해 최소의 문장들이 실행된다. 이것을 흔히 최단 평가 (short circuit evaluation)이라고 한다.
and 와 or 구조를 결합한 유용한 사용법
테스트가 성공적이면 전자를, 실패하면 후자를 실행
[ -f file_one ] && command for true || command for false
문장블록
and나 or 리스트에서 다음과 같이 한 문장이 허용되는 경우에 여러 문장을 사용하기 원한다면 문장 블록을 만들기 위해 중괄호{}에 문장을 포함시킬 수 있다.
get_confirm && {
grep -v "$cdcatnum" $tracks_file > $temp_file
cat $temp_file > $tracks_file
echo
add_record_trakcs
}
posted by progh2
변수
기본적으로 모든 변수는 숫자값을 가지는 경우에도 스트링으로 간주, 필요에 따라 적절히 숫자로 인식할 것이다. 또한 대소문자를 구분하며 변수에 값을 부여할 때를 제외하고는 변수 앞에 $ 문자를 추가할 필요가 있다. 또한 스트링에 빈 칸이 포함된다면 큰 따옴표를 사용해야 한다. 그리고 값을 부여시 등호 양쪽에 빈칸이 없어야 한다.
[CODE]#!/bin/sh myvar="Hi rhere" echo $myvar echo "$myvar" echo '$myvar' echo $myvar echo Enter some text read myvar echo '$myvar' now equals $myvar exit 0[/CODE]
환경변수 - 쉘 스크립트가 시작될 때 초기화되는 환경의 값들을 가진 변수.
[CODE]$HOME 현재 사용자의 홈 디렉토리 $PATH 명령을 검색하는 디렉토리들의 목록. 콜론으로 구분 $PS1 대개 $인 명령 프롬프트 $PS2 추가적인 입력을 요구할 때 사용되는 2차 프롬프트. 대개 > $IFS 입력필드구분자. 쉘이 입력을 받아들일 때 단어를 구분하는 데 사용하는 문자의 목록으로, 대개 빈 칸, 탭, 새 줄 문자이다. $0 쉘 스크립트의 이름 $# 전달된 파라미터의 수 $$ /tmp/tmpfile_$$와 같이 종종 독특한 임시 파일 이름을 생성하기 위해 스크립트에서 사용하는 쉘 스크립트의 프로세스 ID[/CODE]

파라미터 변수
[CODE]$1, $2, ... 스크립트에 주어진 파라미터 $* 환경 변수 IFS의 첫 문자로 구분되고, 하나의 변수에 저장되는 모든 파라미터의 목록 $@ IFS 환경 변수를 사용하지 않는 $*에 대한 변형 [/CODE]

조건
test와 [] - 조건이 만족되었는지의 여부를 가리키는 test 명령의 종료코드는 조건적인 코드가 실행되었는지를 결정한다.
if test -f fred.c
then
...
fi
위와 같은 뜻..
if [ -f fred.c ]; then
...
fi
[]와 테스트되는 조건 사이에 빈칸이 추가되어야 한다.

스트링비교
string1 = string2 두 스트링이 같으면 참
string1 != string2 두 스트링이 같지 않으면 참
-n string 두 스트링이 널이 아니면 참
-z string 두 스트링이 널(빈 스트링)이면 참
산술비교
ex1 -eq ex2 두 수식이 같으면 참
ex1 -ne ex2 두 수식이 같지 않으면 참
ex1 -gt ex2 ex1이 ex2보다 크면 참
ex1 -ge ex2 ex1이 ex2보다 크거나 같으면 참
ex1 -lt ex2 ex1이 ex2보다 작으면 참
ex1 -le ex2 ex1이 ex2보다 작거나 같으면 참
! exp 두 수식이 거짓이라면 참 (또는 그 반대)
파일 조건
-d file 파일이 디렉토리면 참
-f file 파일이 파일이면 참 ( -e 대용으로도 많이 쓰인다. )
-e file 파일이 존재하면 참
-r file 파일이 읽기가능하면 참
-w file 파일이 쓰기가능이면 참
-x file 파일이 실행가능이면 참
-g file 파일에 set-group-id가 설정되면 참
-u file 파일에 set-user-id가 설정되면 참


프로그램 제어
if - 예문 하나로 설명 끝.
[CODE]#!/bin/sh echo " Is it mornig? Please answer yes or no" read timeofday if [ "$timeofday" = "yes" ]; then echo "Good morning" elif [ "$timeofday" = "no" ]; then echo "Good afternoon" else echo "Sorry, $timeofday not recognized. Enter yes or no" exit 1 fi exit 0[/CODE]
[ $timeofday = "no" ] 식으로 표현할 경우 변수값이 null 이면 [ = "no" ] 식이 되버려 에러가 발생하므로 "$timeofday" 라고 표현해주어야 한다.
for
for variable in values
do
statements
done

[CODE]#!/bin/sh for file in $(ls f*.sh); do echo $file done exit 0[/CODE]
while
while condition
do
statements
done

[CODE]#!/bin/sh foo=1 while [ "$foo" -le 20 ] do echo "$foo Here we go again" foo=$(($foo+1)) done exit 0[/CODE]
until
[CODE]until condition do statements done[/CODE]

[CODE]#!/bin/bash until who | grep "$1" > /dev/null do sleep 60 done # 경고음을 내고 사용자에게 알려준다. echo -e \a echo "*** $1 has just logged in ***" exit 0[/CODE]
case
[CODE]case var in pattern [ | pattern ] ...) statements;; pattern [ | pattern ] ...) statements;; ... esac[/CODE]

[CODE]#!/bin/bash echo "Is it morning? Please answer yes or no" read timeofday case "$timeofday" in [yY] | [yY][eE][sS] ) echo "Good Morning";; [nN] | [nN][oO] ) echo "Good Afternoon";; * ) echo "Sorry, answer not recognized" exit 1;; esac exit 0[/CODE]
posted by progh2
출력 재지정
> 덮어쓰기
>> 파일에 추가
표준 ,에러 출력 재지정
ls a * > lsout.txt 2> lserr.txt
>& 표준, 에러 출력의 결합
ls a * > lsouterr.txt 2>&1
출력 버리기(bit bucket 사용)
ls a * > /dev/null 2>&1

권한주기
$ chmod u=rwx,go=rx first.sh
유닉스에서는 파일이 있는 디렉토리에 대해 쓰기 권한을 가질 경우 파일을 삭제할 수 있다는 것을 기억하기 바란다. 안전한 상태가 되기 위해서는 안전하게 유지하기를 원하는 디렉토리에 대한 쓰기 권한을 root에만 부여하는 것이 좋다.
posted by progh2
유닉스 철학에 대해 다룬 내용. 번역이 어색한 부분이 있지만 =_= 취지를 이해하며 그냥 넘어가자. 단순성과 필터와 개방형 파일방식 부분에 대해서는 크게 공감이 간다.



출처 - 비기닝 리눅스 프로그래밍
C로 프로그래밍하는 것은 어떤 플랫폼에서든지 많은 점에서 비슷하지만, 유닉스 개발자들은 프로그램과 시스템 개발의 특별한 관점을 가지게 된다.
유닉스 운영체제는 독특한 프로그래밍 스타일을 요구한다. 다음은 전형적인 유닉스 프로그램과 시스템에서 제공하는 몇 가지 특성이다.

단순성 : 가장 유용한 많은 유닉스 유틸리티는 매우 간단하고, 그 결과 작고 이해하기 쉽다. KISS(Keep It Small and Simple)는 배우기 좋은 기술이다. 크고 복잡한 시스템은 더 크고 복잡한 버그를 가질 수 있고, 모든 개발자들은 디버깅을 원하지 않을 것이다!

집중성 : 프로그래밍 한 가지 일을 제대로 수행하도록 만드는 것이 더 좋다. "다양한 특징"을 가지는 프로그램을 사용하거나 다루는 것은 어려울 수 있다. 한 가지 목적을 가지는 프로그램은 더 나은 알고리즘이나 인터페이스가 개발될 때 개선하기도 쉽다. 유닉스에서는 하나의 큰 프로그램을 통해 사용자의 요구에 대응하기보다는 종종 필요할 때마다 더 많은 요구에 부응하기 위해서 여러 작은 유틸리티를 함께 사용한다.

재사용이 가능한 컴포넌트 : 애플리케이션의 핵심이 라이브러리를 통해 유효하도록 만들기 바란다. 간단하지만 융통성 있는 프로그래밍 인터페이스를 가지고 체계적으로 문서화된 라이브러리는 다른 사람들이 변형판을 만들거나, 새로운 애플리케이션 분야에 해당 기술을 적용하도록 도와줄 것이다. 예를들어, 단일 데이터베이스 관리 프로그램이 아니라 재사용이 가능한 함수의 모음인 dbm 데이터베이스 라이브러리가 있다.

필터 : 많은 유닉스 애플리케이션은 필터로 사용될 수 있다. 즉, 입력을 받아들이고 출력을 생성한다. 유닉스는 색다른 방법으로 여러 프로그램을 결합하여 아주 복잡한 애플리케이션을 개발하게 해주는 특징을 제공한다. 물론, 이런 형태의 재사용은 방금 설명한 개발 방식에 의해 가능한 것이다.

개방형 파일 형식 : 매우 성공적이고 유명한 유닉스 프로그램은 평범한 ASCII 텍스트의 환경 설정파일과 데이터 파일을 사용한다. 프로그램을 개발할 떄 이런 평범한 조건이 주어진다면 아주 좋을 것이다. 이것은 사용자들이 환경 설정 항목을 변경하고 검색하기 위해 표준 도구를 사용할 수 있게 하고 데이터 파일에 대해 새로운 기능을 수행하기 위한 새 도구의 개발을 쉽게 해준다. 이것의 좋은 예는 기호의 위치에 대한 정보를 검색 프로그램에서 사용할 수 있는 일반적인 수식으로 기록하는 ctags 라는 소스 코드 상호 참조 시스템이다.

융통성 : 사용자들이 프로그램을 얼마나 정교하게 사용할 것인지를 정확히 예상하는 것은 불가능하다. 프로그램을 개발할 때에는 가능한 융통적이어야 한다. 필드나 레코드의 수에 임의의 제한을 설정하지 않기 바란다. 가능하다면, 프로그램을 네트워크와 관련시키고, 지역 컴퓨터뿐 아니라 네트워크에서도 실행할 수 있게 작성하기 바란다. 결코 사용자들이 모든 것을 잘 알고 있다고 스스로 자만심을 갖지 않기 바란다.
posted by progh2
출처 - 비기닝 리눅스 프로그래밍 2nd

정적 라이브러리의 한 가지 단점은 많은 프로그램을 실행하고 각각이 모두 같은 라이브러리의 함수를 사용할 때, 메모리에 같은 함수의 많은 사본이 존재하게 되고, 결국 프로그램 파일 자체가 많은 함수의 사본을 가지게 된다는 문제가 있다. 이러한 문제를 해결한 것이 공유라이브러리의 개념이다.
공유라이브러리는 정적 라이브러리와 같은 장소에 저장되며 고유한 확장자를 가진다. 전형적인 리눅스 시스템에서 표준 C 공유 라이브러리는 /lib/libc.so.N 이다. 여기서 N은 주 버전을 뜻하며 현재 6이다.
프로그램이 공유 라이브러리를 사용할 때는 함수 코드 자체를 가지는 것이 아니라 실행 시에 유효한 공유 코드에 대한 참조를 가지도록 링크된다. 그 결과로 프로그램이 실행되고 메모리에 로드될 때 함수에 대한 참조가 이루어지며 필요에 따라서 메모리 내에 로드되는 공유 라이브러리에 대해서 함수 호출이 수행된다. 이러한 방법은 하나의 공유 라이브러리가 한번에 많은 어플리케이션에 의해 사용되고 디스크에 하나만 존재하면 된다. 추가적인 이득은 이 라이브러리가 의존하는 프로그램에 상관없이 독립적으로 갱신될 수 있다는 것이다.



ldd
동적 로더는 리눅스 시스템에서 공유 라이브러리를 로드하고 클라이언트 프로그램의 함수 참조를 해결하는 일을 다루는 프로그램이다. ld.so 나 ld-linux.so.2 등이 있으며 공유 라이브러리를 찾기 위해 검색하는 추가 위치를 /etc/ld.so.conf 에 설정하고 ldconfig로 갱신할 수 있다. ldd를 사용하여 프로그램에 필요한 공유 라이브러리를 확인할 수도 있다.
$ ldd program
manpage
http://man.kldp.org/wiki/FrontPage?action=GetManPage&lang=ko&man=ldd&sec=all

공유 라이브러리는 많은 점에서 마이크로소프트 윈도우즈에 사용되는 동적링크 라이브러리와 비슷하다. .so 라이브러리는 .DLL 파일에 대응하고 실행시에 요구되는 반면, .sa 라이브러리는 프로그램 실행 파일에 호함되는 .LIB 파일과 비슷하다.
posted by progh2
출처 - 비기닝 리눅스 프로그래밍 2nd

아래 4개의 파일이 있다고 할 때..
fred.c
[CODE]/* fred.c */ #include <stdio.h> void fred(int arg) { printf("fred: you passed %d ", arg); }[/CODE]
bill.c
[CODE]/* bill.c */ #include <stdio.h> void bill( char *arg) { printf("fred: you passed %s ", arg); }[/CODE]
lib.h
[CODE]/* lib.h */ void bill(char *); void fred(int);[/CODE]
program.h
[CODE]/* program.c */ #include "lib.h" int main() { bill("Hello World"); exit(0); }[/CODE]
컴파일..
[CODE]$ cc -c fred.c $ cc -c bill.c $ cc -o program program.c bill.o[/CODE]


ar
Static Library를 만들 때 사용한다. 사용법은 다음과 같다.
(bill.o 와 fred.o 두 오브젝트 파일을 합쳐 libfoo.a 를 만들고자 할 때 )
ar crv libfoo.a bill.o fred.o
manpage
http://man.kldp.org/wiki/GetManPage?action=GetManPage&lang=en&man=ar


ranlib
정적 라이브러리를 성공적으로 사용하기 위해서 일부 시스템, 특히 버클리(Berkeley) 유닉스로부터 파생된 시스템에서는 라이브러리 목차를 만들 필요가 있는데, 이를 위해 ranlib을 사용한다. 리눅스와 같이 GNU 소프트웨어 개발 도구를 사용할 때에는 이러한 것이 필요하지 않으며 또한 실행한다 하더라도 문제가 없다.
ranlib libfoo.a

manpage
http://man.kldp.org/wiki/GetManPage?action=GetManPage&lang=en&man=ranlib



정적라이브러리의 사용
이렇게 만든 정적라이브러리는 다음과 같이 사용할 수 있다.
cc -o program program.o libfoo.a
또는
cc -o program program.o -L. -lfoo
-L. 옵션은 컴파일러엑 라이브러리를 현재 디렉토리에서 찾도록 지시한다. -lfoo 옵션은 컴파일러에게 libfoo.a라는 라이브러리를 사용하도록 지시하고, 공유라이브러리인 libfoo.so가 존재한다면 이것을 사용하게 한다.



nm
오브젝트 파일, 라이브러리, 실행 프로그램에 어떤 함수들이 포함되는지 살펴보기 위해서는 nm 명령을 사용할 수 있다.
nm program
nm libfoo.a

manpage
http://man.kldp.org/wiki/GetManPage?action=GetManPage&lang=en&man=nm
posted by progh2
제1장 시작하기
유닉스 프로그램 PATH
유닉스는 PATH 변수에서 항목을 구분하기 위해 MS-DOS와 같이 세미콜론(;)이 아니라 콜론(:)을 사용한다는 것에 주의하기 바란다. 유닉스가 콜론을 먼저 사용하기 시작했으므로 유닉스가 왜 다른 문자를 선택했는지에 대해서 의문을 가질 필요는 없다! 다음은 PATH 변수의 예이다.
[CODE]/usr/local/bin:/usr/bin:.:/home/neil/bin:/usr/X11R6/bin[/CODE]
여기서 PATH 변수는 표준 프로그램 위치, 현재 디렉토리(.), 사용자의 홈 디렉토리와 X윈도우 시스템에 대한 내용을 가진다.

이맥스
이맥스 튜터리얼 -> C + h, t
C + v 다음페이지
M + v 이전페이지
C + x c 끝내기(!)

man vs. info
info 가 man 보다 보통 더 유용하다!

헤더파일
대개 /usr/include와 서브디렉토리에 위치한다. 또, C 컴파일러에서 -I (아이) 플래그를 지정하여 서브 디렉토리나 다른 어떤 디렉토리의 헤더 파일을 사용할 수 있다.
[CODE]$ gcc -I/usr/openwin/include fred.c[/CODE]
종종 헤더 파일에서 특별한 정의문과 함수 원형을 찾기 위해 grep 명령을 사용하는 것은 편리하다. 프로그램으로부터 종료 상태를 반환하기 위해 사용되는 정의문의 이름을 알 필요가 있다고 가정하자. 간단히, /usr/include 디렉토리로 이동하고 예상되는 이름으로 grep을 사용한다. 다음과 같이 할 수 있다.
[CODE][07/18_14:44][progh2@aged:~]$ cd /usr/include/ [07/18_14:44][progh2@aged:/usr/include]$ grep EXIT_ *.h argp.h:#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ argp.h:#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */ argp.h: (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) argp.h: (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) argp.h: (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \r stdlib.h:#define EXIT_FAILURE 1 /* Failing exit status. */ stdlib.h:#define EXIT_SUCCESS 0 /* Successful exit status. */ [07/18_14:44][progh2@aged:/usr/include]$[/CODE]

라이브러리 파일
라이브러리(libraries)는 재사용이 가능하도록 작성된 미리 컴파일된 함수의 모임이다. 대개 /lib 와 /usr/lib에 저장된다. C 컴파일러나 (더욱 정확히)링커는 기본적으로 표준 C 라이브러리를 검색하므로 검색할 라이브러리를 알 필요가 있다. 따라서 표준 디렉토리에 라이브러리를 저장해 두고 컴파일러가 이것을 찾도록 요구하는 것은 충분치 않으며 라이브러리는 독특한 명명 전통을 따르고 명령 라인에서 지정될 필요가 있다.
라이브러리 이름은 항상 lib으로 시작하며 c라이브러리를 가리키는 c나 수치 연산 라이브러리를 가리키는 m과같이 라이브러리의 내용을 가르키는 부분이 나타난다. 이름의 마지막 부분은 마침표(.)로 시작하고, 라이브러리의 형태를 지정한다.
전형적인 정적 라이브러리를 가르키는 .a
공유 라이브러리를 가리키는 .so 와 .sa
일반적으로 라이브러리는 ls /usr/lib을 통해서 볼 수 있듯이 정적 라이브러리와 공유 라이브러리의 형태로 존재한다. 컴파일러에게 전체 경로 이름을 지정하거나 -l 플래그를 사용하여 라이브러리를 찾도록 지시할 수 있다. 예를 들어, 다음은 함수에 대한 참조를 해결하기 위해 표준 C 라이브러리 외에 수치연산 라이브러리를 검색하도록 지시한다.
[CODE]$cc -o fred fred.c /usr/lib/libm.a[/CODE]

비슷한 결과를 다음을 통해 얻을 수도 있다.
[CODE]$cc -o fred fred.c -lm[/CODE]
-lm은 표준 라이브러리 디렉토리의 하나인 /usr/lib에 있는 libm.a라는 라이브러리에 대한 단축기능(shorthand)이다. -lm 표기 방식의 추가적인 장점은 공유 라이브러리가 존재할 때 컴파일러가 이것을 자동으로 선택한다는 것이다.
라이브러리는 일반적으로 헤더 파일과 같이 표준의 장소에 저장되지만, 컴파일러에서 대문자의 -L 플래그를 사용하여 검색 디렉토리에 추가할 수 있다. 예를들어, 다음은 디렉토리 /usr/openwin/lib에 존재하는 라이브러리 libX11의 버전을 사용하여 x11fred라는 프로그램을 컴파일하고 링크할 것이다.
[CODE]$cc -o x11fred -L/usr/openwin/lib x11fred.c -LX11[/CODE]
posted by progh2
prev 1 2 next