시프_정리
날짜: 2022년 12월 13일
15. Threads Synchronization
- Data Sharing
******* 시험출제예상 *******
- 전역변수 volatile 안 쓰면 캐싱이 일어나서 각 스레드마다 레지스터에 존재하는 copy에서 값을 가져와 더하기때문에 값에 오류가 생긴다.
- pthread_cancel 다른 스레드 종료 | pthread_exit 내가 나를 종료
- Race condition & Critical section & Mutual exclusion
- Locks(Mutex)
- available(얻을수있다) | aquired(얻을수없다)
- 획득한 스레드를 owner라고 한다.
- pthread_mutex_
- trylock(&mutex): 즉시 리턴, 0 or error
- lock(&mutex): 획득 가능 할때 리턴, 0 or error
- unlock(&mutex) & destroy(&mutex) 0 or error
16. Issues in Multi-thread Application
- Dining-philosopher problem
- ps(철학자) pp(젓가락)
- pthread_mutex_lock(pp→lock[ps→id]) 왼쪽젓가락잡으려
- pthread_mutex_lock(pp→lock[(ps→id + 1)%phil_count]) 오른쪽젓가락잡으려
- Deadlock
- 홀수번철학자는 왼쪽부터 잡고 짝수번은 오른쪽부터 시도한다.
- Mutex with Condition variable
- Sending signal to multi threads
- kill(getpid(), SIGTERM)
- 자기 종료하면서 다른 애들도 unordered로 종료시킨다.
- kill(getpid(), SIGTERM)
17. File IO(1)
- Directory 또한 일종의 File, 파일들이 실제 위치하는 곳까지 직접 연결될 수 있게 연결지점을 만들어 준다.
- . .. / ~/
- File Table
- 프로그램이 프로세스화 될때 부여되며 프로세스마다 존재한다.
- fd: 012(stdin,stdout,stderr) = File Descriptor table의 인덱스
- File Entry = {inode,offset,mode}
int open(name, flags, mode)
******* 시험출제예상 *******
- return fd or -1
- flags
- O_RDONLY, O_WRONLY, O_RDRW 중 하나는 필수
- O_APPEND, O_CREAT, O_EXCL(파일 존재시 에러 with O_CREAT), O_TRUNC
- mode
- I_IRWX + {U,G,O}
- I_I + {R,W,X} + {USR,GRP,OTH}
- or just 0644
int creat(name,mode)
= open(name,O_WRONLY|O_CREAT|O_TRUNC,mode)ssize_t read(fd,buf,len)
- return 읽어온 바이트 수 or -1
- 중요
while(len!=0 && (ret=read(fd,buf,len))!=0){ if(ret<0) ERROR len -= ret; buf += ret; }
ssize_t write(fd,buf,count)
- return 쓴 바이트 수 or -1
- 쓰기의 경우 캐시에 쓰고 나중에 한번에 메인 메모리에 업데이트 하는데 이것을 강제하는것이
fsync(fd) return 0 or -1
- 긁어올 때 크게 받아와서 메모리에 다시 접근하는 것을 최소화 한다. Buffered I/O
18. File IO(2)
- inode : 파일의 고유 양수 번호(Type, Access mode, ownership)
- File Structure : {metadata + datablocks, single_indirect, double_indirect, triple_indirect}
- 파일이 너무 커지면 → 파일을 나눠서 여러 파일에 데이터를 저장하는것이 효율적이다. 데이터를 탐색하는데에도 시간이 너무 오래 걸려
off_t lseek(fd,pos,origin)
- return new offset or -1
- origin
- SEEK_CUR
- SEEK_SET
- SEEK_END
ssize_t pread(fd,buf,count,pos)
- pos 부터 count 까지를 읽어온다. offset은 미수정
ssize_t p_write(fd,buf,count,pos)
- fork 하고 각자에서 open하면 다른 fd & offset를 갖는다. → Global File Table에서 다른 File Entry 갖는다.(ref=1,ref=1)
- fork 이전에 open 하고 fork 하면 부모와 자식에서 같은 fd를 갖는다.(각 프로세스의 File Descriptor Table에서 같은 fd 넘버) → Global File Table에서 같은 File Entry 갖는다.(ref=2)
- fork 이후에 각자 코드 진행하더라도 같은 fd(하지만 같은 테이블에서가 아니라 각 테이블에서 같은 fd 넘버)를 갖는다.
******* 시험출제예상 *******
- 따라서 각 프로세스에서 각각 close 해주어야 ref가 다시 0이 된다.
- 중요
fd = open(name,flags,mode)
'''fork'''
if child:
write(fd,buf,count)
else:
lseek(fd,0,SEEK_SET) //offset 처음으로 돌린다.
ret = read(fd,buf,len)
19. File IO(3)
select(n,readfds,writefds,exceptfds,timeout)
n = 들어있는 fd 중 가장큰것 + 1
Macros
- FD_CLR() : 특정 fd unset
- FD_ISSET() : 특정 fd가 사용될 준비가 되어있나요?
- FD_SET() : 특정 fd를 set
- FD_ZERO() : 모든 fd를 unset
중요
******* 시험출제예상 *******
FD_SET(stdin,readfds) FD_SET(stdout,writefds) ret=select(stdout+1,readfds,writefds,NULL,NULL) for(i=0;i<2;i++){ if FD_ISSET(i,&readfds) -> R else NULL if FD_ISSET(i,&writefds) -> W else NULL } //stdin 과 stdout 은 동시에 쓰일 수 없다. //i=0 -> writefds에는 stdin이 없어서 X, readfds에는 set 되어있지만 //FD_ISSET이 있는 printf문에서 이미 stdout을 쓰고있기 때문에 stdin은 사용될 수 없다. //i=1 -> stdout은 writefds에 set되어있고 ready 되어있으므로 W을 출력
mmap(addr,len,prot,flag,fd,offset)
- fd에서 offset 부터 len만큼을 addr에 대응시킨다.
- prot
- PROT_READ
- PROT_WRITE
- PROT_EXEC
- fd의 mode와 대응시켜야한다.
- flag 다른 프로세스와 공유 할 수 있다/없다.
- 메모리에 맵핑할때 overhead 크지만, read,write에 overhead 작다.
munmap(addr,len)
fstat(fd,sb)
sb에 fd 정보들을 담는다.
20. File IO(4)
******* 시험출제예상 *******
- command > filename
- stdout을 stdout하지 않고 파일에 저장(파일을 무조건 truncate)
- command >> filename
- stdout을 stdout하지 않고 파일에 저장(O_CREAT|O_APPEND)
- command 2> filename
- stderr 를 stderr하지 않고 파일에 저장
- command >& filename
- stdin,stderr 출력하지 않고 파일에 저장
newfd = dup(1)
- fd=1이 가르키는 Global File Table 의 entry를 newfd가 가르키게 한다.(같은 offset을 갖는다.)
******* 시험출제예상*******
- fd=1이 가르키는 Global File Table 의 entry를 newfd가 가르키게 한다.(같은 offset을 갖는다.)
dup2(oldfd,newfd)
- newfd가 oldfd가 가르키는 Global File Table의 File Entry를 가르키게 한다.(동일한 offset)
21. Standard I/O
- stdio 는 시스템 콜(to kernel)을 줄이기 위해 자체적인 버퍼를 두어 최대한 시스템콜을 미루어서 성능 저하를 막는다.
File* fopen(path,mode)
- mode
- r r+ : 파일이 없으면 에러를 발생 O_EXCL
- w w+ : O_CREAT | O_TRUNC
- a a+
- return 파일포인터 or NULL
- mode
File* fdopen(fd,mode)
- 이미 열린 fd에서 스트림을 연다. mode 맞춰주어야한다.
fgetc(stream)
- stream에서 한 글자만 가져온다.
fgets(str,size,stream)
- stream에서 (size-1)+\0 혹은 \n을 기준으로 끊어서 읽어온다.(한 줄 읽어오기)
- return str or NULL
ssize_t fread(buf,size,nr,stream)
- buf에 stream에서 size(i.e.e. len(char)) nr개 저장
- return 요소개수 or 다 못읽어왔다면 읽어온 개수
- 개행문자 상관없이 nr개 받아온다.
fputc(c,stream)
fputs(str,stream)
- return 개수 or EOF
fwrite(buf,size,nr,stream)
- buf에 있는 데이터를 size*nr 개 stream에 저장
- return 요소개수 or 읽어온 개수
fflush(stream)
- stdin : 입력버퍼 비운다.
- stdout : 출력버퍼 비운다.(출력한다.)
fseek(stream,offset,whence)
- whence
- SEEK_SET
- SEEK_CUR
- SEEK_END
- 스트림 위치 지정자를 해당 위치로 조정
- 그 이후에 fputs 등을 하면 글을 수정하는거지
- whence
ftell(stream)
- 현재 스트림 위치 조정자를 return
fclose(stream)
- return 0 or EOF
fcloseall()
- 열려있는 fd를 다 닫는다.
스트림 생성 | 스트림 닫기 | 스트림 위치 조정자 | buf | ||
---|---|---|---|---|---|
fopen | fclose | fseek | fgetc | fputc | fread |
fdopen | fcloseall | ftell | fgets | fputs | fwrite |
22. Time
- Hardware clock 보다 System clock이 overhead가 크다.
Time 종류 | Hardware clock |
---|---|
Wall Time | RealTimeClock(RTC) |
Monotonic Time | HighPrecisionEventTimer(HPET) |
Process Time | TimeStampCounter(TSC) |
- time(t) |
|
- 현재 시각을 Epoch 초로 반환 | |
- time(t1) or t1=time(NULL) |
struct timeval(tv_sec, tv_usec)
마이크로초int gettimeofday(timeval,timezone)
- timeval에 현재시각을 넣는다.
struct timespec(tv_sec, tv_nsec)
나노초- POSIX CLOCKS(
clock_id
)- CLOCK_REALTIME : wall time
- CLOCK_MONOTONIC : epoch time
- CLOCK_PROCESS_CPUTIME_ID
- CLOCK_THREAD_CPUTIME_ID
clock_getres(clock_id,timespec)
- clock_id 형식으로 현재 시각을 timespec 에 넣는다.
clock_gettime(clock_id,timespec)
- clock_id 형식으로 현재 시각을 timespec 에 넣는다.
23. Sleeping
sleep(seconds)
: low resolution & signal calls=5 while(s=sleep(s)) //return 아직 덜 잠든 시간
nanosleep(timespec req, timespec rem)
- req에 재우고 싶은 시간 정보, rem에 남은 시간 반환
- return 0 or -1
clock_nanosleep(clock_id,flags,req,rem)
- flag 있으면 절대시간, 없으면 상대시간
- clock_id 형태로 req 만큼 재우고 rem에 남은 시간 반환
select(n,readfds,writefds,exceptfds,NULL)
- timeout 이 NULL 이면 고해상도의 sleep 제공
alarm(seconds)
- SIGALRM 발생
- 중복 발생 하면 가장 최근의 알람으로 바꾸므로 겹치지 않게 해야하며, 남은 시간을 리턴한다.
23. Timer
******* 시험출제예상 *******
- sleep, timer 차이
- process 일정 시간 실행 중지
- process 에게 미래에 notification을 주는것을 schedule
- timer, alarm 차이
- alarm은 주기적으로 반복이 가능하다
- 같은 real-timer를 공유하여 혼용하면 안된다.
- 알람과 타이머 모두 하나이고, 정보를 갈아끼우는 형태이다.
- which
- ITIMER_REAL : wall time 재고 프로세스에 SIGALRM 전송
- ITIMER_VIRTUAL : 프로세스의 유저코드가 실행될때만 시간이 감소, SIGVALRM 전송
- ITIMER_PROF : 유저코드 + 커널 동작 모두 시간이 감소, SIGPROF 전송
- ITIMER_PROF - ITIMER_VIRTUAL : 커널 동작 시간 측정
struct itimerval
- it_val : 처음 울릴 시각
- it_interval : 주기
int setitimer(which, itimerval value, itimer ovalue)
- which
- value를 타이머 정보로 set
- ovalue에는 이전 타이머의 정보를 반환
getitimer(which,value)
- which 타입의 현재 타이머 정보를 value에 담는다.
- itimer 장단점
- 호환성이 좋으나 타입이 세개밖에 없고, 울린것을 아는 방법은 signal밖에 없다.
******* 시험출제예상 *******
- 블록되어지면 여러번 들어와도 한번만 recv된다. msec까지만 지원해 해상도가 낮다.
- POSIX timer
timer_create(clock_id, evp, timerid)
- 타이머
timerid
를 생성만 하고 시간이 흐르진 않아 - clock_id
- CLOCK_REALTIME : wall time
- CLOCK_MONOTONIC : epoch time
- CLOCK_PROCESS_CPUTIME_ID
- CLOCK_THREAD_CPUTIME_ID
- 타이머
timer_settime(timerid, flags, itimerspec value, itimerspec ovalue)
struct itimerspec
- it_interval, it_value (timespec, nsec까지 지원)
- flags
- TIMER_ABSOLUTE or 0(상대시간)
- 타이머정보를 value로 set하고, 옛날 타이머정보를 ovalue에 저장
timer_gettime(timerid, value)
- timerid의 정보를 value에 반환
'시스템프로그래밍' 카테고리의 다른 글
리눅스 파이썬 백그라운드 실행 및 로그 저장 (0) | 2023.01.14 |
---|---|
Basic Linux Commands (0) | 2023.01.05 |