posted by 구름너머 2005. 3. 15. 15:58

1장. wait(2)

차례
1.1절. 사용법
1.2절. 설명
1.3절. 반환값
1.4절. 에러
1.5절. 예제

프로세스 정료를 기다린다.


1.1절. 사용법

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);


1.2절. 설명

주로 fork() 를 이용해서 자식 프로세스를 생성했을때 사용한다. wait() 를 쓰면 자식프로세스가 종료할때까지 해당영역에서 부모프로스쓰가 sleep 모드로 기다리게 된다. 이는 자식프로세스와 부모프로세스의 동기화를 위한목적으로 부모프로세스가 자식프로세스보다 먼저 종료되어서 자식프로세스가 고아 프로세스(PPID 가 1)인 프로세스가 되는걸 방지하기 위한 목적이다.

만약 자식 프로세스가 종료되었다면 함수는 즉시 리턴되며, 자식이 사용한 모든 시스템자원을 해제한다.

그런데 어떤이유로 부모가 wait()를 호출하기 전에 자식 프로세스가 종료버리는 경우도 있다(잘못된 메모리 연산등으로 인한 죽음, 혹은 정상적으로), 이럴경우 자식프로세스는 좀비프로세스가 되는데, wait()함수는 즉시 리턴하도록 되어있다.

wait()의 인자 status 를 통하여 자식 프로세스의 상태를 받아올수 있는데, 자식프로세스의 상태값은 자식프로세스의 종료값 * 256(FF) 이다.


1.3절. 반환값

종료된 자식의 프로세스 ID는 에러일경우 -1 그렇지 않을경우 0을 반환한다.


1.4절. 에러

다양한 원인에 의해서 에러가 발생할수 있으며 아래와 같은 에러 메시지들이 있다.

ECHILD

pid 로 지정된 프로세스가 존재하지 않거나, 해당 pid 가 자신의 자식 프로세스가 아닐경우

ENOTSOCK

s 가 소켓이 아닌 파일일경우

ENOTCONN

소켓이 연결되어 있지 않을경우

ENOBUFS

시스템에 연산을 위해서 이용할수 있는 자원이 부족할때


1.5절. 예제

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>

int main()
{
int pid;
int status;

pid = fork();
// 자식 프로세스
if (pid < 0)
{
perror("FORK ERROR :");
exit(0);
}

if (pid == 0)
{
int i;
for (i = 0; i < 5; i++)
{
printf("Child : %d\n", i);
sleep(2);
}
exit(3);
}
else
{
// 부모프로세스는 자식프로세스가
// 종료할때까지 기다린다.
printf("I wait Child(%d)\n", pid);
wait(&status);
printf("Child is exit (%d)\n", status);
}
}
위의 예제를 컴파일후 실행시키면 다음과 같은 결과를 보여준다.
[root@localhost c_source]# ./wait
I wait Child(12128)
Child : 0
Child : 1
Child : 2
Child : 3
Child : 4
Child is exit (768)

posted by 구름너머 2005. 3. 15. 13:29
main() 함수의 매개변수-> (argc,argv) | c2004/11/11 21:02
http://blog.naver.com/alhone/100007527544

8.9 main() 함수의 매개변수

함수의 매개변수는 일반함수뿐만 아니라, main() 함수에도 적용된다. 왜냐면 운영체제의 입장에서 main()은 하나의 함수에 지나지 않기 때문이다. 따라서 main() 함수는 운영체제와 파일정보 및 자료를 전달하기 위하여 매개변수를 사용할 수 있다.

■ 매개변수 argv와 argc

main() 함수의 형식매개변수는 두개의 변수 argc와 argv로 구성된다.

main(int argc, char *argv[])

argc는 운영체제 상에서 main() 함수를 실행하기 위하여 커맨드 라인(command line)에 작성되는 문자열의 수를 나타내고, argv는 문자열들을 가리키는 포인터 변수이다. main() 함수의 실매개변수는 커맨드 라인에서 실행 파일명 뒤에 작성되는 문자열들이다.

main(int argc, char *argv[])

{ int i;

int n, x=0;

if (argc!=4) /* 커맨드 라인의 문자열 수를 검사 */

exit(1); /* 프로그램 종료 */

for (i=0; i<argc; i++)

printf("%s ", argv[i]); /* argv의 문자열 출력 */

n=atoi(argv[3]); /* 네번째 문자열을 정수로 전환*/

for (i=0; i<n; i++)

x=x+i;

printf("%d ", x);

}

예를 들면 프로그램 실행파일 test가 두개의 입출력 파일 ein과 aus 그리고 한 개의 정수자료를 필요로 한다면, 운영체제 모드에서 라인 커맨드는 "/test ein aus 10"와 같이 작성해야 한다. 그러면 main() 함수의 매개변수 argc는 4가 되고, argv[]에서 argv[0]="test", argv[1]="ein", argv[2]="aus", argv[3]="10"의 값을 갖게 된다.

■ 외부 파일을 main() 함수에 전달하는 방법

첫째, 디스크에 있는 물리적 파일을 프로그램의 논리적 파일로 사용하기 위해서 main() 함수의 매개변수를 main(int argc, char *argv[])처럼 서술한다.

둘째, 매개변수로 전달된 물리적 파일에 대응하는 논리적 스트림 파일을 FILE로 선언한다.

FILE *<논리적 파일명> [,*<논리적 파일명>]...;

FILE *fopen();

셋째, 물리적 파일을 사용목적에 맞도록 열고(open), 함수 fopen()을 통하여 프로그램의 논리적 파일과 관계를 맺도록 서술한다.

1) <논리적 파일명>=fopen( <물리적 파일명>, "<mode>");

2) <논리적 파일명>=fopen("<물리적 파일명>", "<mode>");

fopen() 함수는 파일을 열 때 실패하면, NULL 값을 반환한다. 1) 형식은 파일을 main() 함수의 매개변수를 통하여 전달할 때 사용되고, 2) 형식은 main() 함수의 매개변수를 통하지 않고 프로그램에서 직접 파일을 참조할 때 사용된다.

넷째, 파일 입출력문으로 자료를 처리한 후에는 열어둔 모든 파일을 fclose() 함수로 반드시 닫아야 한다.

fclose (<논리적 파일명>);

파일을 닫는 의미는 입출력 버퍼에 있는 자료를 모두 입출력 파일에 옮겨 쓰고, 파일 끝에 EOF 표시를 붙힌 후, 버퍼와 파일의 제어블록까지 지워버리는 것을 의미한다. 파일이 성공적으로 닫히면 0 값을 반환하고, 실패하면 -1 값을 반환한다.

■ 입출력 파일의 mode

입출력 파일의 <mode>와 그의 기능은 다음과 같다.

"r" : 기존 파일로부터 읽기(read)

"w" : 출력할 파일이 없으면 빈 파일을 만들고, 있으면 빈 파일로 만들어 쓰기

"a" : 파일이 없으면 파일을 생성하고, 있으면 파일 끝에 부쳐 쓰기

"r+" : 기존 파일로부터 읽고 쓰기(read/write)

"w+": 파일 존재여부를 떠나서 빈 파일을 만들어 읽고 쓰기

"a+" : 파일이 없으면 우선 파일을 생성한 후에 읽고 쓰기

다음 프로그램은 main() 함수의 매개변수를 통하여 파일로부터 읽고 쓰기 위한 과정을 서술하고 있다.

/* main() 함수의 매개변수로 프로그램에 연결 */

main(int argc, char *argv[])

{ char c;

FILE *in_fil, *out_fil, *fopen(); /* 논리 스트림 파일 선언 */

in_fil=fopen(argv[1], "r"); /* 물리적 파일과 논리적 파일의 관계를 연결 */

out_fil=fopen(argv[2], "w");

c=fgetc(in_fil); /* 파일로부터 한 문자 읽기 */

..............

fclose(in_fil); fclose(out_fil);

}

다음은 main() 함수에서 매개변수를 사용하지 않고 /usr/ 디렉토리에 있는외부파일 data_in, data_out을 논리파일 in_file과 out_fil에 input과 output용으로 직접연결하는 예이다.

main(void)

{ char c;

FILE *fopen();

FILE *in_fil, *out_fil;

if ((in_fil=fopen("/usr/data_in", "r")==NULL) /* 실패하면 */

{ printf("cannot open file for read!");

exit();

}

........

out_fil=fopen("/usr/data_out", "w");

c=fgetc(in_fil); /* 파일로부터 문자 읽기 */

........

fclose(in_fil); /* 파일 닫기 */

fclose(out_fil);

}

다음은 파일로부터 학생들의 성적을 읽고 처리하는 프로그램으로서 자료구조는 구조체에 대한 배열로 정의했으며, 외부의 입출력 파일은 main() 함수의매개변수를 통하여 프로그램에 연결하였다.

#include <stdio.h>

struct student

{ int id; /* stud ent_id; */

char name[10]; /* student_name; */

int nat, eng, math;

float aver;

} tp[10];

struct student *pt;

main(int argc, char *argv[])

{ FILE *infil, *outfil, *fopen(); /* 논리 스트림 파일 선언 */

infil=fopen(argv[1], "r"); /* 물리파일에 대한 논리파일 연결 */

outfil=fopen(argv[2],"w");

pt=tp; /* pt=&tp[0]; */

/* fscanf()와 fprintf()는 파일로부터의 입출력 함수 */

while (fscanf (infil, "%3d", &pt->id)!=EOF)

{ fscanf(infil, "%10c %3d %3d %3d",

pt->name, &pt->nat, &pt->eng, &pt->math);

pt->aver=(float)(pt->nat+pt->eng+pt->math) / 3.0;

fprintf(outfil, "%3d %13s %6d %6d %6d %7.2f \n",

pt->id, pt->name, pt->nat, pt->eng, pt->math, pt->aver);

++pt;

}

fclose (infil);

fclose (outfil);

}

'UNIX' 카테고리의 다른 글

UNIX 셀 프로그램에서 값 비교하기..  (0) 2005.04.07
wait(2)  (0) 2005.03.15
int argc, char **argv 의 정체가 정말  (0) 2005.03.15
Unix System Programming 5  (1) 2005.03.15
Unix 함수 설명 및 목록  (1) 2005.03.15
posted by 구름너머 2005. 3. 15. 13:27
int argc, char **argv 의 정체가 정말~~~
평점 :
- 1 (1 명)나도 평가하기quinton1 조회: 116답변: 1
답변이 완료된 질문입니다. (2005-02-23 21:09 작성)신고하기
몇 달전에 소켓 프로그래밍에 도전했다가 C언어가 너무 부실해서 다시
C와 C++ 공부하고 소켓으로 오늘 돌아왔습니다.
예전에 전혀 몰랐던 것들이 눈에 들어오기는 하는데
간단한 예제에서 딱 하나 도저히 모르는것이 하나 있으니...
지식인을 검색하니 답변들이 참 많이 나오던데 그래도 도무지 알수가 없네요.
소켓 프로그래밍 처음부터 끝까지 아쭈 꼬박꼬박 빼먹지 않고 나오는 이 녀석

int main(int argc, char **argv)

argc와 argv가 하나의 약속처럼 되어있는 언어인지 알기 쉽게 좀 설명 좀
부탁드리겠습니다.
이거 다시 C++로 돌아가야될지 참 걱정되네요... ^^
질문자가 선택한 답변
re: int argc, char **argv 의 정체가 정말~~~
microcat (2005-02-24 00:13 작성, 2005-02-24 00:14 수정)이의제기 | 신고하기
질문자 평
안녕하세요.

소켓프로그램을 좀 하셨다니까 함수 정도는 쉽게 하나 작성하실 수 있으리라 생각됩니다.

함수의 형태는 일반적으로

return_value Function_Name(Arguments...)형태로 되어 있지요.

자세히 보시면 int main(int argc, char **argv)도 똑같은 형태입니다.

이것을 실행시키는 것은 바로 콘솔 프로그램이지요. 도스라던가 윈도우즈 운영체제일겁니다.

이녀석들 입장에서 보면 이 프로그램은 하나의 함수 형태로 작동하게 되는 것이죠.

서두가 길었군요. 본 설명 들어갑니다.

int argc는 argument count라고 해서 본 프로그램을 실행할 때 매개변수가 몇개 들어갔느냐... 이런 것입니다.

예를 들어서 format이라는 프로그램을 작성했다고 합시다.

format c: /s를 하게 되면 argc의 값은 3이 들어갑니다.

단순히 문자열이 3개 들어갔다고 해서 3입니다.

char **argv(또는 char *argv[])에는 무엇이 들어가느냐하면

argv[0] = "format"
argv[1] = "c:"
argv[2] = "/s"
이것들이 들어가게 됩니다.

이것을 사용하게 되면 매개변수(arguments)로 받아들인 것들을 제어해서

본 프로그램을 제어할 수 있도록 할 수 있습니다.

약속되어 있냐고 물으신다면... 그렇습니다.

프로그래머 입장에서는 그냥 이대로 쓰기만 하면 되는겁니다 ^^;;;

ps. 하나 빼먹었는데 argv는 argument vector인지 value인지 그럴겁니다 ^^;;;

'UNIX' 카테고리의 다른 글

wait(2)  (0) 2005.03.15
main() 함수의 매개변수-> (argc,argv)  (0) 2005.03.15
Unix System Programming 5  (1) 2005.03.15
Unix 함수 설명 및 목록  (1) 2005.03.15
프로세스의 상태를 얻는 매크로  (0) 2005.03.14
posted by 구름너머 2005. 3. 15. 12:52
Unix System Programming 5 | Linux Unix2004/04/24 10:29
http://blog.naver.com/javabuilder/60001947114
제5장. 프로세스

5.1. 프로세스 개념의 복습
UNIX 에서의 프로세스란 간단히 말하면 수행중인 프로그햄 그 자체이며, 이것
은 다른 환경에서 말하는 태스크(task) 개념에 해당한다. 쉘(shell)은 하나의
명령을 수행하기 위하여 어떤 포그램을 시작할 때마다 새로운 프로세스를 새성
한다. UNIX 프로세스 환경은 화일시스템의 디렉토리 트리와 같은 계층적인 구
조를 가진다. 프로세스 트리의 꼭대기에는 하나의 제어 프로세스가 존재하는
데, 이것은 init 라 하는 매우 중요한 프로그램의 수행이며, 궁극적으로 모든
프로세스는 이것으로 비롯된다. 프로세스 간의 통신을 위해 제공되는 시스템
호출들에 대해서는 다음장에서 설명하기로 하고, 여기서는 다음과 같은 핵심적
인 것만을 소개한다.

fork : 호출 프로세스와 똑같은 프로세스를 하나 생성한다. fork 는 가장
기본적인 프로세스 생성 프리미티브이다.
exec : 시스템 호출들의 모임으로서, 각각은 동일한 기능 즉, 한 프로세스
를 그 자신의 기억장소에 새로운 프로그램을 대치시킴으로써 변환시
키는 기능을 수행한다. exec 호출들 각각의 차이는 그들의 매개변수
목록들이 어떤방법으로 작성되는가에 있다.
wait : 프로세스의 동기화(synchronization)를 위한 초보적인 호출이다. 프
로세스를 연관된 다른 프로세스가 끝날때까지 기다리게 한다.
exit : 프로세스를 종료할때 사용된다.

5.2. 프로세스의 생성

5.2.1. fork 시스템 호출
fork 시스템 호출은 기본적인 프로세스 생성 프리미티브이다. 이것을 통하여
UNIX 는 다중처리 시스템(multitasking system)으로 전환된다.

int pid;

pid = fork();

fork 가 성공적으로 수행되면 커널은 호출하는 프로세스의 복사본을 새로운
프로세스로서 생성 한다. 새로 생성된 프로세스를 자식프로세스(child
process)라 하고, fork 를 호출한 프로세스를 부모 프로세스(parent process)
라 한다. fork 의 호출로 자식프로세스가 생성된 후에는 부모프로세스와 자식
프로세스가 동시에 수행 되며, 이때 두 프로세스는 fork 호출문의 바로 다음
문장부터 수행을 계속한다.

프로세스 식별번호
fork 는 인수없이 호출되고, 정수형의 pid 를 돌려준다.

pid = fork();

부모와 자식 프로세스를 구분하는 것은 pid의 값이다. 부모 프로세스는 pid
가 0 이 아닌 양의 정수 값을 갖는 반면 자식 프로세스는 0 을 갖는다. 부모
에게로 돌려주는 pid 값을 자식 프로세스의 프로세스 식별번호(process-id)라
한다.

/* spawn -- demonstrate fork */

main()
{
int pid; /* hold process-id in parent
*/
printf("Just one process so far\n");
printf("Calling fork ...\n");

pid = fork(); /* create new process*/

if(pid == 0)
printf("I'm the child\n");
else if(pid > 0)
printf("I'm the parent, child has
pid %d\n", pid);
else
printf("Fork returned error code,
no child\n");
}

fork 뒤의 if 문에 3 개의 분기(branch)가 존재한다. 첫번째 문기는 변수
pid 값이 0 일때, 자식 프로세스를 위한 동작을 명세하는 것이고, 두번째 문기
는 pid 값이 양수일때에 해당하는 것으로, 부모 프로세스가 해야할 동작을 나
타낸다. 그리고 세번째 분기는 pid 가 음수값(실제는 -1)을 가질 때에 해당하
는데, fork 가 자식 프로세스의 생성이 실패하였을 때의 동작을 말해준다. 이
런 상황은 부모프로세스가 다음과 같은 두종류의 제한을 깨뜨리려고 했을 때
발생한다. 첫째는 시스템 차원에서 허용되는 프로세스의 갯수이고, 둘째는 개
별 사용자가 동시에 수행시킬 수 있는 프로세스의 수에 대한 제한이다. 이런
두 종류의 상황에서 오류변수 errno 는 EAGAIN 이라는 코드를 값으로 가진다.
왜 fork 가 유용한 호출인가를 논의해 보자. 가장 핵심은 fork 가 UNIX 의
다른 기능들과 연관될때 더 유용해진다는 것이다. 예를들어 fork 로 만들어진
부모와 자식 프로세스는 UNIX 에서 제공하는 signal 이나 pipe 등과 같은 프로
세스간의 통신기능을 이용하여 서로 협조해 가면서, 서로 관련되어 있지만 서
로 다른 일들을 해 나갈 수가 있다.

5.3. exec 를 이용한 새 프로그램의 수행

5.3.1. exec 군
exec 군(family) 에 속한 어떤 호출은 새로운 프로그램의 수행을 위해 사용될
수 있다.

char *path, *file;
char *arg0, *arg1, ..., *argn;
char *argv[];
int ret;
.
.
ret = execl(path, arg0, arg1, ..., argn,
(char *)0);

ret = execv(path, argv);

ret = execlp(file, arg0, arg1, ..., argn,
(char *)0);

ret = execvp(file, argv);

exec 의 모든 변종들은 동일한 기능을 수행한다. 즉, 호출 프로세스(exec 를
호출하는)의 기억 장소에 새로운 프로그램을 로드(load)함으로써, 호출 프로세
스가 새 프로그램을 수행하도록 한다. exec 가 성공적으로 수행되면 호출 프로
그램은 완전히 새로운 프로그램으로 대치되고, 그 프로그램의 처음부터 수행은
시작하게 된다. 결과는 새로 만들어진 프로세스 하나만이 존재 하는데, 이 프
로세스는 자기를 호출한 프로세스 와 똑같은 프로세스식별번호를 가진다. exec
는 호출 프로세스와 동시에 수행하는 새로운 부프로세스를 생성하는 것이 아니
라는 점이 중요하다. exec 로 부터의 복귀값은 없다. excl 의 모든 인수는 문
자형의 포인터이다. 첫번째 인수인 path 는 새로이 수행될 프로그램이 들어있
는 화일의 이름을 가리킨다. 이것은 절대 또는 상대적인 유효한 경로이름이어
야한다. execl(혹은 execv)는 쉘명령이 들어있는 화일은 수행시키지 못한다.
두번째 인수 arg0 은 관레적으로 앞자리의 경로이름을 제거한 프로그램 또는
명령의 이름이 된다. 마지막 임을 알리는 표시로 null 포인터가 존재해야 한
다. 디렉토리를 나열하는 프로그램 ls 를 수행하기 위해 execl 을 사용하는 다
음의 프로그램을 살펴보자.

/* runls -- use "execl" to run ls */

main()
{
printf("executing ls\n");

execl("/bin/ls", "ls", "0l", (char *)
0);

/* If execl returns, the call has
failed, so ... */
perror("execl failed to run ls");
exit(1);
}

execl 이 성공적으로 호출되면 호출 프로그램을 제거하여 수행되지 않게 하
고, execl 이 호출되지 않아 호출 프로그램이 살아 남으면 오류가 발생되도록
하는 것이다. 이런 이유로 execl 과 그 변종들이 복귀될때는 항상 -1 을 돌려
준다.

execv, execlp 와 execvp
execv 는 2 개의 인수만을 가진다. 첫째는 수행될 프로그램의 경로이름을 가
지고 있는 문자열을 가리키는 포인터 둘째는 문자 포인터의 배열로서

char *argv[];

로서 선언되어 있다.

/* runls2 -- use execv to run ls */

main()
{
char *av[3];

av[0] = "ls";
av[1] = "-l";
av[2] = (char *)0;

execv("/bin/ls", av);

/* again - getting this far implies
error */
perror("execv failed");
exit(1);
}

execlp 와 execvp 도 execl 과 execv 와 거의 비슷하다. 가장 중요한 차이는
execlp와 execvp 의 첫번째 인수가 경로이름이 아니라 단순히 화일이름을 가리
킨다는 데에 있다.

5.3.2. exec 에 의해 전달된 인수에의 접근
모든 프로그램은 자신의 main 함수로 전달된 인수를 통해서 자신을 호출한
exec 호출의 인수에 접근할 수 있다. 이 인수들은 프로그램의 main 함수를 다
음과 같이 정의함으로써 사용될 수 있다.

main(argc, argv)
int argc;
char **argv;
{
/* body of program */
}

argc 는 인수의 갯수를 나타내는 정수이고, argv 는 인수들의 배열을 가리킨
다. 자신의 첫번째 인수를 제외한 인수들을 표준 출력으로 출력하는 다음의 프
로그램을 살펴보자.

/* myecho -- echo command line arguments */

main(argc, argv)
int argc;
char ** argv;
{
while(--argc > 0)
printf("%s ", *++argv);
printf("\n");
}

5.4. exec 와 fork 의 공동이용
fork 와 exec 를 함께 사용함으로써 프로그래머에게 더 많은 기능을 제공할
수 있다. fork 로 자식 프로세스를 만들고, 그자식프로세스 안에서 exec 를 이
용하면, 부모프로세스의 입장에서는 자신을 죽이지 않고도 전혀 다른 프로그램
을 부프로세스로 가질 수 있게 된다. 간단히 오류 루틴 fatal 과 wait 라는 시
스템 호출이 새로이 소개된다.

/* runls3 -- run ls in a subprocess */

main()
{
int pid;

pid = fork();

/* if parent, use wait to suspend
* execution until child finishes
*/
if(pid > 0){
wait((int*)0);
printf("ls completed\n");
exit(0);
}

/* if child then exec ls */
if(pid == 0){
execl("/bin/ls", "ls", "-l",
(char *)0);
fatal("execl failed");
}

/* getting here means pid is
* negative, so error has
* occurred
*/
fatal("fork failed");
}

fatal 은 한 메세지를 출력하기 위해서 단순히 기존의 perror 를 호출한다.

fatal(s) /* print error message and die */
char *s;
{
perror(s);
exit(1);
}

이 예에서 wait 는 fork 호출로 자식 프로세스를 생성한 직후에 호출된다. 시
스템은 이 호출로 인해 자식이 끝날때까지 부모를 sleep 상태에 둔다.

5.5. 상속된 자료와 화일 기술어

5.5.1. fork 에 있어서의 화일과 자료
fork 로 생성된 자식 프로세서는 부모 프로세스와 거의 똑같다. 특히 부모 프
로세스가 가지고 있던 변수의 값들은 자식 프로세스에게 그대로 전달된다.
(fork 자신으로부터의 복귀값은 예외임). 자식에게 주어지는 변수의 값들은 부
모 프로세스가 가진 변수의 값들의 '복제'이기때문에 기억장소에서 서로 다른
위치에 놓이게 된다. 그러나 fork 이전에 개방된 화일들은 부모와 자식 프로세
스간에 매우 밀접하게 연관 된다. 이것은 각 화일의 읽기-쓰기 포인터가 부모
와 자식사이에서 공유되기 때문이다. 이러한 공유는 읽기-쓰기 포인터가 프로
그램 자체내에 명시적으로 선언되는 것이아니라 시스템이 관리하는 것이기 때
문에 가능하다. 결론적으로 한 자식 프로세스가 어떤 화일에서 정방향으로 포
인터를 전진시키면 부모 프로세스에서도 새로운 위치로 이동된다.

5.5.2. exec 와 개방된 화일
보통 개방된 화일 기술어들도 exec 를 호출했을 때 생성된 프로세스에 전달된
다. 즉, 원래의 프로그램에서 개방된 화일들은 exec 를 통해서 전혀 새로운 프
로그램이 시작될 때도 개방된 상태가 보존된다. 그런 화일들에 대한 읽기-쓰기
포인터들도 exec 호출에 의해 변화되지 않는다. fcntl 루틴을 이용하면 한 화
일과 연관된 close-on-exec 플래그를 조절할 수 있다.

#include <fcntl.h>
.
.
int fd;

fd = open("file", O_RDONLY);
.
.
/* set close-on-exec flag on */
fcntl(fd, F_SETFD, 1);

close-on-exec 플래그는 명령문

fcntl(fd, F_SETFD, 0);

에 의해 off 로 된다. 플래그의 현재 값은 다음과같이 얻어질 수 있다.

res = fcntl(fd, F_GETFD, 0);

정수형 변수 res 는 close-exec 플래그가 화일 기술어 fd 에 대해 on 일때 1
값을 가지며, 그렇지 않으면 0 을 가진다.

5.6. exit 시스템 호출

int status;

exit(status);

exit 은 이미 익숙한 것으로, 프로세스를 종료 시키고자 할때 사용된다. 물론
프로세스는 프로 그램을 수행하며 main 함수의 끝이 도달하거나, main 에서
return 문을 수행할 때에도 종료된다. exit 호출에서 가장 중요한 것은 모든
개방된 화일 기술어를 닫는 것이다.

5.7. wait 를 이용한 프로세스의 동기화

int retval, status;

retval = wait(&status);

retval = wait((int *)0);

wait 는 자식 프로세스가 수행되고 있는 동안 부모 프로세스의 수행을 일시적
으로 중단시킨다 . 자식이 수행을 마치면, 기다리던 부모는 수행을 재개한다.
하나 이사의 자식이 수행되고 있으면, wait 는 자식 프로세스들 중 하나가 최
초로 종료되는 시간에 복귀된다.

pid = fork(); /* create new process */

if(pid == 0){
/* child */
/* do something..*/
}else{
/* parent, so wait for child */
wait((int *)0);
}

fork 와 wait 의 조합은 자식 프로세스가 exec를 통해 완전히 서로 다른 프로
그램을 수행 하도록 되어있을 때 이용된다. wait 가 -1 을 돌려주면 살아있는
자식 프로세스가 없다는 의미이고, 이 경우 errno 는 오류 코드 ECHILD 를 가
지게 된다.

5.8. 좀비와 불완전한 종료
1. 부모 프로세스가 wait 를 수행하지 않고 있는 상태에서 자식이 종료할때
2. 하나 이상의 자식 프로세스가 수행되고 있는 상태에서 부모가 종료할때

1 의 경우 종료하는 프로세스는 일종의 잊혀진 장소로 옮겨져서 좀비(zombie)
가 된다. 좀비 프로세스는 프로세스를 제어하기 위해 커널이 관리하고 있는 테
이블에 등록되어 있으면서 커널의 다른 자원들은 사용하지 않는다.
2 의 경우, 부모는 정상적인 종료가 허용된다. 부모 프로세스의 자식들(좀비
를 포함한)은 시스 템의 초기화 프로세스에게 맡겨진다(초기화 프로세스가 부
모의 역활을 함).

5.9. smallsh : 명령어 처리기
-- 생략

5.10. 프로세스 속성
각각의 UNIX 프로세스는 몇가지의 속송(attribute)들을 가지는데, 이 속성은
프로세스의 수행과 수행계획(scheduling), 화일 시스템의 보안 유지등을 시스
템이 조정하는데에 도움을 준다.

5.10.1. 프로세스 식별번호
시스템은 각 프로세스에게 프로세스 식별번호라는 음이 아닌 정수를 부여한
다. 프로세스 식별번호는 해당 프로세스가 종료하면 다시 사용될 수 있지만,
한 시점에서는 유일하게 프로세스를 지정한다. 프로세스 0 은 수행 계획 프로
세스(scheduler) 이고, 프로세스 1 은 /etc/init 프로그램을 수행하고 있는 초
기화 프로세스이다. 시스템 호출을 이용하여 자신의 프로세스 식별 번호를 참
조할 수 있다.

pid = getpid();

getppid 를 사용하면 호출 프로세스의 부모 프로세스의 프로세스식별번호를
얻을 수 있다.

ppid = getppid();

5.10.2. 프로세스 그룹과
프로세스 그룹식별번호
UNIX 는 프로세스들이 어떤 그룹에 속하는 것을 허용한다. 각 프로세스 그룹
은 프로세스 그룹식별번호라 불리는 정수로 표시된다. 처음에 프로세스는 fork
나 exec 를 호출할 때 자신의 프로세스 그룹식별번호를 새로운 프로세스에게로
상속한다. 그러나 한 프로세스는 setpgrp 를 호출함으로써 자신을 새로운 그룹
에 넣을 수 있다.

newpg = setpgrp();

newpg 는 새로운 프로세스 그룹식별번호인데, 실은 호출 프로세스의 프로세스
식별번호와 동일한 값이다. 한 프로세스는 자신의 현재 프로세스 그룹식별 번
호를 getpgrp 라는 시스템 호출을 이용하여 얻을 수 있다.

pgid = getpgrp();

자신의 프로세스 그룹식별번호를 수정하지 않은 프로그램이라면, pgid 의 값
은 자신의 조상중의 쉘 프로세스의 프로세스식별번호가 될 것이다.

5.10.3. 환경
프로세스의 환경(environment)은 간단히 말하면 null 로 끝나는 문자열의 모
임인데, 프로그램 안에서는 문자형 포인터의 null 로 끝나는 배열 로 표현된
다. 관레적으로, 각 환경 문자열은 다음과 같은 형태를 가진다.

name = something

프로그래머는 프로그램의 main 함수의 인수 리스트에 envp 라는 또 하나의 인
수를 첨가함으로써, 프로세스의 환경을 직접사용할 수 있다. 다음의 프로그램
은 envp 의 유형을 보여준다.

main(argc, argv, envp)
int argc;
char **argv, **envp;
{
/* do something */
}

5.10.4. 현재 작업 디렉토리
앞의 4 장에서 살펴보았듯이, 각 프로세스는 현재 작업 디렉토리와 연관된다.
현재 디렉토리 의 초기상태는 그 프로세스가 fork 나 exec 로 시작될 때 물려
받는다. 다시 말하면 한 프로세스는 그의 부모와 같은 디렉토리에 놓여진다.
자식 프로세스가 chdir 을 호출함으로써, 그 위치를 변화시켜도 부모 프로세스
의 현재 디렉토리는 변하지 않는다. 이런 이유로 표준 cd 명령어는 쉘 자체에
내장된 명령어이고, 프로그램에 대응하는 것이 아니다.

5.10.5. 사용자 식별번호와 그룹식별번호
각 프로세스는 실제 사용자식별번호와 그룹식별번호와도 연관된다. 이것들은
그 프로세스를 호출한 실제 사용자와, 그 사용자가 속한 그룹의 식별번호들이
다. 더 중요한 것은 유효 사용자식별번호와 유효그룹식별번호인데, 이것들은
어떤 사용자가 한 화일을 접근할 수 있는 지의 여부를 결정하는데 사용된다.
대부분의 경우에 유효사용자 식별 번호와 실제사용자 식별번호는 같다. 프로스
랩 화일의 set-user-id 비트가 1 이면, 그 프로그램이 exec 로 호출될 때, 그
프로세스 의 유효 사용자식별번호는 그 프로세스를 시작시킨 실제사용자가 아
니라. 프로그램 화일의 소유자가 된다. 프로세스와 연관된 사용자와 그룹의 식
별번호를 얻는데 쓰이는 시스템호출이 몇가지 있다.

int uid, euid, gid, egid;

/* get real user-id */
uid = getuid();

/* get effective user-id */
euid = geteuid();

/* get real group-id */
gid = getgid();

/* get effective group-id */
egid = getegid();

유효사용자와 그룹의 식별번호를 지정할 때에는 다음의 두가지 호출이 유용하
다.

int status, newuid, newgid;
.
.
/* set effective user-id */
status = setuid(newuid);

/* set effective group-id */
status = setgid(newgid);

두 루틴의 복귀값이 0 이면 수행의 성공을, 1 이면 실패를 나타낸다.

5.10.6. 화일크기의 제한 : ulimit
시스템 V 에는 프로세스마다 wait 시스템 호출을 이용하여 만들 수 있는 화일
의 크기에 제한이 있다. 화일 크기의 제한은 ulimit 라는 시스템 호출로 조작
된다.

long retval, newlimit, ulimit();
int cmd;
.
.
retval = ulimit(cmd, newlimit);

현재 화일의 크기 제한을 얻어내기 위하여 프로그래머는 cmd 인수를 1 로 하
고 ulimit 를 호출한다. 복귀값인 retval 은 512 바이트를 한 블럭으로 하는
단위이다. 화일 크기의 제한을 바꾸려면 cmd 를 2 로 하고, 화일의 크기에 대
한 새로운 제한을 512 바이트 블럭을 단위로 newlimit 에 저장한다.

5.10.7. 프로세스 우선 순위 : nice
시스템이 cpu 시간의 비율을 결정할 때, 특정한 프로세스는 그의 nice 값(정
수)에 의거하여 시간이 할당된다. Nice 값은 0 에서 시스템이 정하는 최대값
(보통은 39)까지이다. 큰 값을 가질수록 프로세스는 낮은 우선순위를 가진다.
nice 호출은 하나의 인수를 필요로 하는데, 그것은 현재의 nice 값에다 증가시
키려는 만큼의 양의 정수값, 즉 증가분을 말한다.

nice(5);

수퍼 사용자만이 인수를 음수로하여 우선순위를 높일수가 있다.

'UNIX' 카테고리의 다른 글

main() 함수의 매개변수-> (argc,argv)  (0) 2005.03.15
int argc, char **argv 의 정체가 정말  (0) 2005.03.15
Unix 함수 설명 및 목록  (1) 2005.03.15
프로세스의 상태를 얻는 매크로  (0) 2005.03.14
crontab 등록하기  (2) 2005.02.23
posted by 구름너머 2005. 3. 15. 11:57

아래 사이트를 참고하세요. 잘 되어 있네요.

http://www.joinc.co.kr/modules/moniwiki/wiki.php/function_list

'UNIX' 카테고리의 다른 글

int argc, char **argv 의 정체가 정말  (0) 2005.03.15
Unix System Programming 5  (1) 2005.03.15
프로세스의 상태를 얻는 매크로  (0) 2005.03.14
crontab 등록하기  (2) 2005.02.23
HPUX11 관리 팁 | HP-UX  (0) 2004.12.08
posted by 구름너머 2005. 3. 14. 20:44
프로세스의 상태를 얻는 매크로 | C2004/09/09 10:32
http://blog.naver.com/semi7623/100005635882

매크로 : 상태설명

- WIFEXITED(status) : 프로세스가 정상 종료했을 경우 참 값을 리턴한다.
- WEXITSTATUS(status) : 프로세스가 정상 정료했을 때 exit() 함수의 인자 값 중 하위 8비트의 값을 얻을 수 있다.
- WIFSIGNALED(status) : 프로세스가 시그널에 의해 종료되었을 경우 참값을 리턴한다.
- WTERMSIG(status) : 프로세스가 시그널에 의해 종료된 경우 시그널 번호를 리턴 한다.
- WCOREDUMP(status) : 코아 파일의 발생 여부를 리턴 한다.
- WIFSTOPPED(status) : 프로세스가 현재 수행이 일시 중단된 상태일 경우 참 값을 리턴 한다.
- WSTOPSIG(status) : 프로세스를 일시 중단시킨 시그널 번호를 리턴 한다.

'UNIX' 카테고리의 다른 글

Unix System Programming 5  (1) 2005.03.15
Unix 함수 설명 및 목록  (1) 2005.03.15
crontab 등록하기  (2) 2005.02.23
HPUX11 관리 팁 | HP-UX  (0) 2004.12.08
/etc/nsswitch.conf  (0) 2004.12.08
posted by 구름너머 2005. 2. 23. 12:47
1. korn shell에서 crontab 등록하기
--------------------------------------------------
ksh
$ EDITOR=vi
$ export EDITOR
$ crontab -e

ksh
EDITOR=vi
export EDITOR
crontab -e

0 1 * * * /data2/site/src/run_proc.sh
:wq

$ crontab -l
0 1 * * * /data2/site/src/run_proc.sh
$ exit
-----------------------------------------------------------


2. 플래그
-e 사용자의 crontab 파일의 사본을 편집하거나 또는 아직 crontab 파일이 없으면 편집 세션을 시작합니다. 편집이 완료될 때, 항목이 사용자의 crontab 파일로서 설치됩니다. 편집 세션은 EDITOR 환경 변수에 의해 지정되는 편집기를 사용하여 시작됩니다. 디폴트 편집기는 vi입니다.
-l crontab 파일을 나열합니다.
==> $crontab -l

-r crontab 디렉토리에서 사용자 crontab 파일을 제거합니다.
==> 명령어 내리기전 다시 한번 주의!!@

-v cron 작업의 상태를 나열합니다.


3. crontab 파일 항목 형식
crontab 파일은 각 cron에 대한 항목을 포함합니다. 항목들은 개행 문자로 분리됩니다. 각 crontab 파일 항목은 다음 형태로 공백이나 탭으로 분리된 6개 필드를 포함하고 있습니다.

* * * * * command
| | | | |
| | | | +--> 요일 (0-6, 0은 일요일입니다)
| | | +--> 월 (1-12)
| | +--> 일 (1-31)
| +--> 시간 (0-23)
+--> 분 (0-59)

minute(분) hour(시) day_of_month(일) month(월) weekday(요일) command(명령)
이들 필드는 다음 값을 승인합니다.

minute(분) 0 - 59
hour(시) 0 - 23
day_of_month(일) 1 - 31
month(월) 1 - 12
weekday(요일) 일요일부터 금요일까지를 나타내는 0 - 6
command(명령) 쉘 명령

각 필드에 대해 반드시 값을 지정해야 합니다. command 필드를 제외하고, 필드 다음에 들어갈 수 있습니다.

지정된 범위에 있는 숫자. 5월에 명령을 수행하려면, 월 필드에 5를 지정하십시오.
두 수를 대시로 분리하여 두 수 자체도 포함하는 범위를 나타내는 범위 지정. 화요일부터 금요일까지 cron 작업을 수행하려면, weekday 필드에 2-5를 입력하십시오.
숫자들을 쉼표로 분리하여 나열한 숫자 리스트. 1월의 첫날과 마지막 날에 명령을 수행하려면, 일 필드에 1,31을 입력합니다.
*(별표)는 모든 허용되는 값을 의미합니다. 매 시간마다 작업을 수행하려면, hour(시) 필드에 별표를 지정하십시오.
주: 앞에 역슬래시(% 포함)가 오는 모든 문자는 문자 그대로 처리됩니다. 날짜의 지정은 두 필드(날짜와 요일)에 의해 이루어질 수 있습니다. 둘다를 요소로 지정할 경우, 둘다 고수하십시오. 예를 들어 다음과 같이 입력합니다.
0 0 1,15 * 1 command
이 명령은 모든 월요일뿐만 아니라 각 달의 1일과 15일에 command를 수행합니다. 단 하나의 필드로 날짜를 지정하려면, 다른 필드는 *를 포함해야 합니다.

'UNIX' 카테고리의 다른 글

Unix 함수 설명 및 목록  (1) 2005.03.15
프로세스의 상태를 얻는 매크로  (0) 2005.03.14
HPUX11 관리 팁 | HP-UX  (0) 2004.12.08
/etc/nsswitch.conf  (0) 2004.12.08
네트워크 구성  (0) 2004.12.08
posted by 구름너머 2004. 12. 8. 10:51

출처 : cafe.naver.com/crazysystem

1. 커널 bit 확인하기

% getconf KERNEL_BITS

2. ps -o 옵션을 사용하려면 다음 환경변수를 설정한다.

% setenv UNIX95 XPG4

3. 기타 명령들...

% ipcs -b (IPC 상태 출력)

% bdf (df 와 동일한 명령어)

% model (모델명 출력)

% ndd -get /dev/tcp tcp_fin_wait_2_timeout (FIN WAIT 타임아웃시간 출력, ndd 는 network tuning)

4. 메모리 보는 명령

% dmesg

% swapinfo

% vmstat

5. DEPOT 소프트웨어 설치

% /usr/sbin/swinstall -s /tmp/sdk14_14202_1100.depot

(이미 설치되어있는것을 재설치할 경우 reinstall 옵션을 UI상에서 추가해준다.)

6. CPIO 풀기

% cat *.cpio | cpio -idcv

또는

% cpio -idcmv < *.cpio

7. Network Configuration (set_parms 의 사용)

i)시스템의 이름 및 네트웍과 관련된 모든 정보를 수정할 때

# /etc/set_parms initial

ii) 시스템의 IP 어드레스를 수정할 때

# /etc/set_parms ip_address

iii) 시스템의 게이트웨이, 서브넷 마스크, DNS 및 NIS정보를 수정할 때
# /etc/set_parms addl_netwrk

iv) /etc/set_parms 를 실행시키면 사용법을 알 수 있다.

v) 수동으로 했던 방법 (IP주소 변경)

# ifconfig lan0 down

# ifconfig lan0 192.168.0.3 netmask 255.255.255.0up

# route add default 192.168.0.1

# vi /etc/hosts

...

192.168.0.3 myhpux.domain.com myhpux

...

# vi /etc/rc.config.d/netconf

...

INTERFACE_NAME[0]=lan0
IP_ADDRESS[0]=192.168.0.3

SUBNET_MASK[0]=255.255.255.0
BROADCAST_ADDRESS[0]=192.168.0.255
INTERFACE_STATE[0]=up
DHCP_ENABLE[0]=0


ROUTE_DESTINATION[0]=default
ROUTE_GATEWAY[0]=192.168.0.1
ROUTE_COUNT[0]=1

...

8. Network 관리 command

i) 네트웍H/W 의 이상을 진단하는 명령

# lanadmin(landiag)

ii) 네트웍 구성 및 확인을 위해 사용하는 명령 ifconfig
# ifconfig lan0 (상태 확인할 때)
# ifconfig lan0 192.1.1.1 netmask 255.255.255.0 up (네트웍 구성할 때)
iii) 네트웍의 routing 상태를 확인함
# netstat -r

iv) 네트웍의 H/W address(예: 0x0060b018cd17) 및 상태를 확인할 수 있음

# lanscan

9. 물리적 디스크 정보 확인하기

i) 우선 설치된 디스크의 리스트를 확인

# ls /dev/rdsk/*

ii)diskinfo 명령을 이용하여 디스크의 상세 정보를 확인한다.

# diskinfo /dev/rdsk/XXXX

ex)

# ls /dev/rdsk/*
/dev/rdsk/c2t1d0 /dev/rdsk/c3t15d0


# diskinfo /dev/rdsk/c2t1d0
SCSI describe of /dev/rdsk/c2t1d0:
vendor: HP
product id: DVD-ROM 305
type: CD-ROM
size: 0 Kbytes
bytes per sector: 0


# diskinfo /dev/rdsk/c3t15d0
SCSI describe of /dev/rdsk/c3t15d0:
vendor: HP 73.4G
product id: MAS3735NC
type: direct access
size: 71687369 Kbytes
bytes per sector: 512

10. 시스템 소프트웨어 설치 내역 확인 (by superuser)

# /usr/sbin/swlist -l product

11. HPUX 에서 GSP 들어가기 -> 부팅되는 중에 Ctrl-B

12. ISL 모드에서 싱글 유저로 부팅하기

OS 부팅되기 직전 10초가량 시간내에 Enter를 치면 ??? 상태로 진입한다.

(display 에 잘 나와있으니 주의해서 보면 알수있음)

???> boot

ISL? Y/N> Y

ISL> boot -is

'UNIX' 카테고리의 다른 글

프로세스의 상태를 얻는 매크로  (0) 2005.03.14
crontab 등록하기  (2) 2005.02.23
/etc/nsswitch.conf  (0) 2004.12.08
네트워크 구성  (0) 2004.12.08
Unix 서버 비교  (0) 2004.11.23