Skip to content

Latest commit

 

History

History
201 lines (150 loc) · 14.3 KB

hongo.md

File metadata and controls

201 lines (150 loc) · 14.3 KB

으악 못생겼어 나중에 수정할게요 일단 여기로... https://velog.io/@hgo641/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC

프로세스 시스템 작업의 단위 메모리에 적재되어있는 프로그램 프로세스 구성요소 프로세스 메모리

스택 : 일시적인 데이터들을 저장(함수 매개변수, 함수 리턴값 등), 컴파일 타임에 크기가 결정돼서 무한으로 할당할 수 없음.(스택오버플로우) 힙 : 동적인 데이터 저장(동적 배열 등). 런타임에 결정돼서 정해진 크기가 없음. 데이터 : 정적 변수 저장 텍스트 : 코드 저장 -> 같은 프로그램으로부터 생성된 프로세스여도, 텍스트 부분만 동일하고 다른 부분들은 다를 수 있다.

PCB(Process Control Block) 프로세스 상태, 프로세스 아이디, 스케줄링 정보, 우선순위 프로그램 카운터 : 다음에 어느 코드를 실행해야 할 지를 저장한다. (프로세스 메모리의 코드부분을 가리키는 포인터가 존재!) 프로세서 레지스터 : 레지스터에 변수값등을 저장! 열고있는 파일들의 정보 스레드 정보 프로세스 상태

준비 : 메모리에 적재된 상태이며, cpu만 할당받으면 언제든 일할 수 있는 상태 대기 : 메모리에 적재된 상태가 아닐 수도 있으며, cpu를 할당받아도 일할 수 없는 상태 프로세스 스케줄링 큐

OS에는 준비큐와 대기큐가 존재한다. 디바이스마다 큐들이 존재할 수 있으며, 각 큐들은 PCB를 연결리스트로 저장하고 있다.

문맥 교환 프로세스가 어디까지 실행했는지, 현재 어떤 상태인지등 프로세스 상태를 파악하기 위한 모든 정보를 문맥이라고 한다. pc, 레지스터, 프로세스 메모리, PCB가 포함된다. CPU가 실행할 작업을 유저프로세스A에서 유저프로세스B로 바꾸는 것을 문맥 교환이라고 한다. (유저프로세스에서 커널프로세스로 전환하는 것은 문맥 교환이라고 부르지 않음! 유저프로세스->유저프로세스보다 오버헤드가 적다.) 문맥 교환시에는 유저프로세스A에 대한 정보를 이후 복구할 수 있게 PCB에 기록. 해당 PCB를 커널의 메모리에 저장하고, 유저프로세스B의 정보를 메모리로 적재한다. 문맥 교환시에는 어떤 프로세스도 수행할 수 없기에 순수한 오버헤드가 된다. 때문에 문맥 교환을 적절한 시간에 하는 것이 중요!

프로세스 생성 프로세스는 트리 구조이며, 부모 프로세스가 자식 프로세스를 생성하는 형태이다. 시스템이 부팅될 때 가장 최상위 프로세스인 systemd프로세스가 생성된다. (pid = 1)

자식 프로세스는 부모 프로세스의 데이터를 복사해온다.

전부 복사해오지 않는 경우도 있다. 리눅스의 경우, 일단은 자식 프로세스가 부모 프로세스와 같은 주소를 가리키게 하고, 자식 프로세스가 새로운 데이터를 써야하는 시점에 실제로 복사를 수행하게 한다.(copy on write) fork() 부모 프로세스에서 자식 프로세스를 생성하는 시스템 콜이다.

fork()의 반환값 차이 부모 프로세스는 fork()의 반환값이 자신의 아이디이다. ( pid > 0) 자식 프로세스는 0을 반환한다. exec() 자식 프로세스는 부모 프로세스의 주소 공간을 복사해올 수 있다. 그러나 부모 프로세스와 완전히 다른 프로그램을 자식 프로세스에서 실행하고 싶다면, exec() 시스템 콜을 사용하면 된다.

exec()를 실행하면, 프로세스는 exec()의 매개변수로 들어온 프로그램으로 전환된다. 메모리에 저장된 값 자체가 전부 초기화되고 새로운 프로그램을 가져온다. 때문에 exec()를 수행할 경우, 부모 프로세스의 모든 주소를 복사해오는 것은 낭비이다.

ex. execlp("/bin/ls", "ls", NULL) : 새로운 프로그램인 bin/ls로 전환. execlp()의 아래 코드는 실행하지 않음.

wait() 부모 프로세스는 자식 프로세스와 병행해서 작업을 수행할 수도 있지만, wait()를 사용하여 자식 프로세스가 종료될 때까지 대기할 수도 있다.

exit() 프로세스를 종료하기 위해 exit()를 사용한다. 자식 프로세스 스스로 일을 다 마쳐 exit()될 수도 있고, 외부에서 자식 프로세스를 exit()시킬 수도 있다.

좀비 프로세스와 고아 프로세스 좀비 프로세스 : 자식 프로세스는 종료되었지만, 부모 프로세스가 아직 wait()를 호출하지 않은 상태 부모 프로세스와 자식 프로세스를 병행해서 실행하고 싶다면 언제 wait를 해야하지? -> 자식 프로세스를 백그라운드로 실행시키면, 좀비 프로세스가 되지 않는다? -> 시그널 핸들링 : 자식프로세스가 종료되면 시그널 핸들러에게 시그널 전달. 시그널 핸들러에서 wait수행

고아 프로세스 : 자식 프로세스는 실행중이지만, 부모 프로세스가 종료된 상태 프로세스간 통신(IPC) 공유 메모리 방식 : 프로세스가 같은 주소공간을 공유 메시지 전달 방식 : 커널을 통해 메시지를 전달 메시지 전달 방식은 커널을 통해 시스템 콜을 호출하는 등 부가적인 작업이 존재해서 공유 메모리 방식보다 느리다. 공유 메모리 방식은 처음에 공유 메모리 영역을 구축할 때만 시스템 콜 사용.

메시지 전달 모델은 충돌을 회피할 필요가 없기 때문에 적은 양의 데이터를 교환하는 데 유용한다 레전드 미스테리 -> 공유 메모리 방식은 메모리의 전송 속도로 수행할 수 있기에 대량의 데이터에 적합하지만 메시지 전달 방식은 공유 메모리 방식에 비해 속도가 더 느리다. 그니까 대량의 데이터를 전송하면 손해다~ 라는 의미?... ...??

그럼 공유 메모리 방식은 다른 네트워크에 속하는 프로세스끼리는 할 수 없는건가? 클라우드 스토리지 같은 걸 공유 메모리라고 우기진 않겠지? "통상 공유 메모리 영역은 공유 메모리 세그먼트를 생성하는 포르세스의 주소 공간에 위치한다"

공유 메모리 시스템 일반적으로 한 프로세스가 다른 프로세스의 메모리에 접근하는 것을 금지하지만, 공유 메모리는 예외적인 케이스. 동시에 동일한 위치에 데이터를 쓰지 않도록 책임져야 함. (어떻게 책임져야 할 지는 나중에 알려주겠지 ...)

버퍼도 공유 메모리 방식이넫, 생산자-소비자 모델에서 생산자와 소비자 프로세스들을 병행으로 실행하려면 버퍼가 있어야한다. 생산자는 버퍼에 데이터를 열심히 쌓아두고, 소비자는 버퍼에서 데이터를 꺼내가야 둘이 병행으로 실행 가능.

메시지 전달 시스템 같은 주소 공간을 공유하지 않고도 프로세스간 통신이 가능한 기법. send()와 receive() 시스템 콜 사용

몇 가지 특성들이 존재.

직접 통신 vs 간접 통신 동기식 vs 비동기식 자동 버퍼링 vs 명시적 버퍼링 직접 통신 직접 통신은 특정 프로세스를 지목해서 보내는 방식(ex. 프로세스P와 Q가 통신중일 때, send(P, message), receive(Q, message) )

두 프로세스 사이에서만 통신이 일어난다.

프로세스 이름이 바뀌면, 코드 수정해야함 (프로세스 이름 : 실행 파일 이름이나 프로세스 생성 시의 인자 등에 의해 결정)

간접 통신 특정 프로세스를 지목해서 통신하지 않고, 메일 박스나 포트를 통해 통신.

프로세스 사이에 메일박스라는 중간 저장소가 존재

메일박스의 아이디가 존재. 메일박스 A가 있을 때, send(A, message), receive(A, message)식으로 통신.

메일박스는 한 프로세스 또는 운영체제에 의해 소유될 수 있다.

프로세스에 의해 소유됐다면, 그 메일박스는 프로세스의 주소 공간 일부. 즉, 프로세스가 종료될 때 메일박스도 사라진다. 자동 버퍼링 & 명시적 버퍼링 프로세스들간 교환되는 메시지들은 임시 큐에 들어간다. 큐를 구현하는 방식은 세 가지가 있다.

무용량 : 큐의 길이가 0. 대기 불가능. 송신자는 수신자가 메시지를 수신할 때까지 기다려야함. 유한 용량 : 큐의 길이가 유한. 최대 개수까지 차면 송신자는 기다려야함. 무한 용량 : 큐의 길이가 무한. 무용량은 버퍼가 없는 메시지 시스템이라고 부른다. 유한 용량과 무한 용량은 자동 버퍼링이라고 부른다.

큐가 다 찼을 때 전략.

무기한 기다림 최대 n밀리초동안 기다림 기다리지 않고 즉시 복귀 메시지를 일시적으로 캐시 - 운영체제에 전달하여 보존. 메시지 전달 시스템 예시1 - 파이프 파이프는 보통 단방향 통신을 지원하며, 부모와 자식 프로세스 사이에 사용되는 것이 일반적이다.

파이프 설계시 고려해야할 것 단방향 vs 양방향 반이중 vs 전이중 (반이중은 한 순간에 한 방향으로만 전송 가능, 전이중은 동시에 양방향으로 전송 가능) 프로세스간 부모-자식같은 관계가 존재하는 가 같은 컴퓨터안의 프로세스인가? 분산 환경의 프로세스인가? 일반 파이프(익명 파이프) 생산자-소비자 형태의 파이프. 생산자는 파이프의 한 종단에 데이터를 쓰고, 소비자는 반대 종단에서 읽는다. 일반 파이프는 한쪽으로만 데이터를 전송할 수 있으며, 단방향 통신만 가능하다. (양방향 통신하고 싶으면 파이프 두 개 만드셈)

일반 파이프는 파이프를 생성한 프로세스외에는 접근할 수 없다. 그래서 부모-자식 프로세스들끼리 통신하는 데 쓰임. (자식 프로세스는 부모 프로세스로부터 열린 파일을 상속받는다.)

(예시에서 설명해주는 파이프는 파일인데, 파일 형태만 있는지는 모르겠음)

지명 파이프 일반 파이프는 프로세스들이 통신하는 동안에만 존재. (통신하는 두 프로세스들이 정해져있음) 지명 파이프는 프로세스가 종료되어도 계속 존재함. 지명 파이프는 여러 프로세스들이 사용할 수 있는 파이프임. (부모-자식 관계 필요 없음)

메시지 전달 시스템 예시1 - 소켓 소켓은 네트워크 프로그래밍에서 주로 사용되는 IPC방법.(로컬에서도 쓸 수 있긴함) 소켓은 통신의 극점을 의미함. 두 프로세스가 네트워크상에서 통신하려면 두 개의 소켓이 필요. 소켓은 IP주소와 포트번호 두 가지로 구별함.

클라이언트 프로세스가 연결을 요청하면, 호스트 프로세스가 포트 번호를 부여. (이때 포트 번호는 1024보다 큰 정수인데 소켓용으로 정해둔듯)

소켓은 분산 환경에서 널리 사용되지만, 저수준 통신 방법이다. 스레드간에 구조화되지 않은 바이트 스트림만을 통신하기 때문! (그래도 채팅에선 개꿀이죠?) 대안으로 더 높은 수준의 통신 기법인 RPC가 존재함.

RPC(원격 프로시저 호출) 프로시저 : 걍 코드 집합. 함수라고 보면 됨. 네트워크를 통해서 함수를 호출하는 방법.

IPC 방식과는 달리 RPC 통신에서 전달되는 메시지는 구조화 되어있다. 메시지 구성요소

헤더 : 메시지 길이, 메시지 유형, 인증정보 등 원격지 포트에서 listen중인 RPC demon의 주소가 지정 실행할 함수의 식별자 함수에 들어갈 매개변수 RPC vs REST API by 챗지피티님

RPC (Remote Procedure Call) 특징: Procedure-Centric: RPC는 프로시저 중심적입니다. 클라이언트가 서버의 특정 함수 또는 프로시저를 원격으로 호출하고, 결과를 받는 방식입니다.

데이터 전송 포맷: 주로 Protocol Buffers, Thrift, gRPC 등과 같은 이진 데이터 포맷을 사용합니다. 이는 데이터를 효율적으로 직렬화하여 전송합니다. 상태를 가질 수 있음: RPC는 상태를 가질 수 있으며, 일부 프레임워크는 연결을 통한 상태 유지를 제공합니다. 사용 시나리오: 성능이 중요한 상황: RPC는 데이터의 효율적인 전송과 빠른 응답 시간을 강조하므로, 성능이 중요한 상황에서 적합합니다. 내부 마이크로서비스 통신: 내부 마이크로서비스 간의 통신에 많이 사용됩니다. 이진 데이터 전송이 필요한 경우: 이미지, 비디오 등과 같은 바이너리 데이터를 효과적으로 처리할 수 있습니다. REST API (Representational State Transfer API) 특징: Resource-Centric: REST API는 자원 중심적입니다. 각 자원은 고유한 URI를 가지며, HTTP 메소드(GET, POST, PUT, DELETE)를 사용하여 상태를 전송합니다. 데이터 전송 포맷: 주로 JSON 형식을 사용합니다. 이는 사람이 읽고 쓰기 쉽고, 브라우저에서도 처리하기 편리합니다. 무상태(Stateless): REST는 상태를 저장하지 않는 무상태 아키텍처를 가지며, 각 요청은 모든 필요한 정보를 포함하고 있어야 합니다. 사용 시나리오: 웹 애플리케이션 개발: REST는 주로 웹 애플리케이션 개발에서 사용되며, 클라이언트-서버 간의 통신을 간단하게 유지할 수 있습니다. 클라이언트가 상태를 관리하는 경우: REST는 무상태 아키텍처이므로 클라이언트가 상태를 관리해야 하는 경우에 적합합니다. HTTP 메소드 활용: REST는 HTTP 메소드를 사용하여 간단하게 CRUD(Create, Read, Update, Delete) 기능을 제공할 수 있습니다. 언제 어떤 것을 선택해야 할까요? 복잡성 및 효율성: RPC는 성능이 중요하고, 직렬화된 이진 데이터를 사용할 수 있습니다. REST는 간단하고 유연하지만, 데이터는 주로 텍스트 형식인 JSON을 사용하므로 직렬화 및 파싱 오버헤드가 있을 수 있습니다. 상태 유무: RPC는 상태를 가질 수 있지만, REST는 무상태입니다. 클라이언트가 상태를 유지해야 하는지 여부에 따라 선택할 수 있습니다. 표준화된 프로토콜: RPC는 프레임워크에 따라 다른 프로토콜을 사용할 수 있지만, REST는 HTTP를 사용하므로 표준화된 프로토콜을 사용합니다.