exit: A program calls exit()
to exit. - remove the body - becomes a zombie until the parent calls wait()
wait: A program calls wait()
and waits for the child to exit. - if the child already called exit()
- remove its process descriptor - else - wait until the child exits
algorithm:
for(;;){
printf("$");
scanf("%s", buf);
x=fork();
if (x==0) execve(buf,0,0);
else wait();
}
Actual code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(){
int x,y,status, i;
char buf[50];
char * argv[10];
for(i=0;i<10;i++){ // use a finite loop instead of an infinite one
printf("$");
scanf("%s", buf); // get command.
argv[0]=buf;
argv[1]=0;
x=fork();
if (x==0){ // child
printf("I am child to execute %s\n", buf);
y=execve(buf, argv, 0);
if (y<0){
perror("exec failed");
exit(1);
}
} else wait(&status);
}
}
kernel (pid=0)
fork: init (pid=1)
exec: /sbin/init (pid=1)
fork & exec: iscsid
rsyslogd
..........
/usr/sbin/sshd (pid=1262)
fork : sshd : linuxer (pid=5198)
fork : sshd: linuxer@pts/0 (pid=5201)
fork & exec: -bash (pid=5202)
fork & exec: vi cli.c (pid=6420)
In gdb
, use set follow-fork-mode child
or set follow-fork-mode parent
to debug child or parent process.
$ gdb ex1
(gdb) set follow-fork-mode child
/bin/ls
์ฒ๋ผ ์คํํ์ผ์ ์ ์ฒด ๊ฒฝ๋ก๋ฅผ ์จ์ฃผ์ด์ผ ํ๋ค.cp ex1.c ex2.c
์ฒ๋ผ ์ธ์๊ฐ ์ฃผ์ด์ง๋ ๋ช
๋ น์ด๋ ์คํ์ํฌ ์ ์๋ค.pstree
๋ ์คํ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ํธ๋ฆฌํํ๋ก ๋ณด์ฌ์ฃผ๋ ์ ๋์ค ๋ช
๋ น์ด์ด๋ค. -p
๋ โshow pidsโ๋ก PID๋ฅผ ํจ๊ป ์ถ๋ ฅํ๋ ์ต์
์ด๋ค.
scanf("%s", buf);
๋ก buf
๋ฅผ ์
๋ ฅ๋ฐ์ ๋ค,
if (strcmp(buf, "exit") == 0) exit(1);
๋ฅผ ์ถ๊ฐํ์ฌ, exit
์ ์
๋ ฅ ๋ฐ์์ ๊ฒฝ์ฐ ํ๋ก๊ทธ๋จ์ ์ข
๋ฃํ ์ ์๊ฒ ํ์๋ค.
gets()
or fgets()
to read the command.fgets()
๋ก ์ฌ์ฉ์์ ์
๋ ฅ์ ๊ณต๋ฐฑ์ ํฌํจํ์ฌ ๋ฐ์์๋ค. ๊ทธ ํ, strtok
๋ก ์
๋ ฅ์ ๊ณต๋ฐฑ์ ๊ธฐ์ค์ผ๋ก ๋ถ๋ฆฌํด์ฃผ๊ณ , ๊ทธ๊ฒ์ argv[]
๋ฐฐ์ด์ ์ ์ฅํ์ฌ execve
ํจ์์ ๋๊ฒจ์ฃผ์๋ค.
&
) &
at the end of the command.์ฌ์ฉ์์ ์
๋ ฅ์ ๋งจ ๋ง์ง๋ง์ด &
์ธ์ง์ ๋ฐ๋ผ wait
์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ์ฝ๋๋ฅผ, 45๋ฒ ์ค๋ถํฐ 49๋ฒ ์ค๊น์ง ์์ ํด์ฃผ์๋ค.
์คํ์ฌ๋ถ๋ฅผ ๊ฒ์ฆํ๊ธฐ ์ํด ์๋์ ๊ฐ์ด ๋ฌดํ๋ฃจํ๋ฅผ ๋๋ โloopโ๋ผ๋ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์๋ค.
๊ทธ ํ ์๋์ ๊ฐ์ด ์คํํ์ ๋, ์ ์์๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
ls -l
, cp f1 f2
, etc), build a full path such as โ/bin/lsโ, โ/bin/cpโ, etc. and perform exec. Use sprintf()
to build the full path.์๋๊ฒฝ๋ก๋ก ์
๋ ฅ ๋ฐ์ ๋ช
๋ น์ด์ ๊ฒฝ๋ก๋ฅผ ์ ๋๊ฒฝ๋ก๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ ์ํด ์ฐ์ , 7๋ฒ ์ค์ PATH
๋ฅผ โ/bin/โ๋ก ์ ์ํด์ฃผ์๋ค.
๊ทธ ํ, sprintf
๋ฅผ ์ด์ฉํด ์๋๊ฒฝ๋ก๋ก ๋์ด์๋ argv[0]
๋ฅผ ์ ๋๊ฒฝ๋ก๋ก ๋ณํํด์ฃผ์๋ค. (41๋ฒ ์ค ~ 43๋ฒ ์ค)
getenv("PATH")
to retrieve PATH environment variable and use strtok()
to extract each system path. Display each system path line by line.int main(void) {
char * path = getenv("PATH");
printf("%s\n", path);
return 0;
}
์์ ๊ฐ์ด ์ฝ๋๋ฅผ ๊ตฌ์ฑํ์ฌ ์คํํ์ ๋์ ์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
/Users/oneonlee/opt/anaconda3/bin:/Users/oneonlee/opt/anaconda3/condabin:/usr/local/opt/bison/bin:/usr/local/bin:/Library/Frameworks/Python.framework/Versions/3.7/bin:/Library/Frameworks/Python.framework/Versions/3.9/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
๊ฒฝ๋ก๋ค์ด :
๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ตฌ๋ถ๋์ด ์์ผ๋ฏ๋ก ์ด๋ฅผ strtok()
๋ฅผ ์ฌ์ฉํ์ฌ ๋ถ๋ฆฌํด์ฃผ์๋ค.
getenv("PATH")
to obtain the pointer to the value of the PATH environment variable. Note you need to copy the string of the PATH variable into another char array before you start extracting each path component with strtok()
since strtok()
destroys the original string.์ ๋๊ฒฝ๋ก๋ก ์ ๋ ฅ ๋ฐ์์ ๊ฒฝ์ฐ(45๋ฒ ์ค)์ ์๋๊ฒฝ๋ก๋ก ์ ๋ ฅ ๋ฐ์์ ๊ฒฝ์ฐ(55๋ฒ ์ค)๋ก ๋๋์ ๊ฐ๊ฐ์ ์ํฉ์ ๋ง๊ฒ ๋์ํ์๋ค.
์๋๊ฒฝ๋ก๋ก ์
๋ ฅ ๋ฐ์์ ๊ฒฝ์ฐ์๋ getenv("PATH")
๋ฅผ ์ฌ์ฉํ์ฌ, execve
ํจ์ ์คํ์ด ์ฑ๊ณตํ ๋๊น์ง env
๋ฅผ ๋ฐ๊ฟ๊ฐ๋ฉฐ while๋ฌธ์ ์คํํ๋ค.
dup(x)
duplicates fd[x]
in the first empty entry in the fd table. Run following program and explain the output. Assume f1 has โhello my boyโx=open("f1", O_RDONLY, 00777);
int y;
y=dup(x);
printf("x:%d y:%d\n", x, y);
char buf[50];
int k=read(x, buf, 5);
buf[k]=0;
printf("buf:%s\n", buf);
k=read(y, buf, 5);
buf[k]=0;
printf("buf:%s\n", buf);
x=open("f2", O_WRONLY|O_CREAT|O_TRUNC,00777);
printf("x:%d\n", x);
int y;
close(1);
y=dup(x);
printf("x:%d y:%d\n", x, y);
write(1, "hi there", 8);
$ cat f1 > f3
will redirect the output of โcat f1โ to file f3.