728x90
운영체제
운영체제 개요
- 프로그램은 매우 단순한 일을 한다.
- 명령어를 반입(fetch)하고, 해석(decode)하고, 실행(execute) 한다.
- 명령어 작업을 완료한 후, 프로세서는 다음 명령어로 또 그 다음 명령어로 프로그램이 완전히 종료될 때까지 실행을 계속한다.
- 운영체제는 가상화(virtualization)라고 불리는 기법을 사용한다. 운영체제는 프로세서, 메모리, 또는 디스크와 같은 물리적인 자원을 이용해서 일반적이고, 강력하고, 사용이 편리한 가상형태의 자원을 생성한다. 때문에 운영체제를 가상머신(virtual machine) 이라고 한다.
- 사용자 프로그램의 프로그램 실행, 메모리 할당, 파일접근과 같은 가상머신과 관련된 기능들을 운영체제에게 요청할 수 있도록, 운영체제는 사용자에게 API를 제공한다. 보통 운영체제는 응용프로그램이 사용 가능한 수 백개의 시스템콜을 제공한다.
- 마지막으로, 가상화는 많은 프로그램들이 CPU를 공유하여 동시에 실행 될 수 있게 한다. 프로그램들이 각자 명령어와 데이터를 접근 할 수 있게한다. 프로그램들이 디스크등의 장치를 공유 할 수 있게 한다. 이러한 이유로 운영체제는 자원관리자(resource manager)라고도 불린다. CPU, 메모리, 및 디스크는 시스템의 자원이다. 효율적으로 이들 자원을 관리하는 것이 운영체제의 역할이다.
CPU 가상화
- 하드웨어의 도움을 받아 운영체제는 CPU 시스템에 많은 수의 가상 CPU가 존재한다는 환상(illusion)을 만들어 낸다. 하나의 CPU 또는 소규모 CPU 집합을 무한개의 CPU가 존재하는 것처럼 변환하여 동시에 많은 수의 프로그램을 실행시키는 것을 CPU가상화(virtualiziong the CPU)라 한다.
메모리 가상화(Virtualizing Memory)
- 우리가 사용하고 있는 컴퓨터에서의 물리메모리 모델은 바이트의 배열이다. 메모리를 읽기 위해서는 데이터에 주소를 명시해야 한다. 메모리에 쓰기(혹은 갱신) 위해서는 주소와 데이터를 명시해야 한다.
- 메모리는 프로그램이 실행되는 동안 항상 접근된다.
- 운영체제가 메모리 가상화(virtualizing memory)를 하기 때문에 이런 현상이 생긴다. 각 프로세스는 자신만의 가상 주소공간을 갖는다. 운영체제는 이 가상 주소공간을 컴퓨터의 물리메모리로 매핑한다. 하나의 프로그램이 수행하는 각종 메모리 연산은 다른 프로그램의 주소공간에는 영향을 주지 않는다.
병행성(Concurrency)
- 프로그램이 한 번에 많은 일을 하려 할 때(동시에) 발생하는 그리고 해결해야 하는 문제들을 가리킬 때 이 용어를 사용한다.
- 병행성 문제는 운영체제 자체에서 발생한다. 하지만 운영체제만의 문제는 아니다. 멀티 쓰레드 프로그램도 동일한 문제를 들어낸다.
영속성(Persistence)
- DRAM 같은 장치는 데이터를 휘발성(volatile) 방식으로 저장하기 때문에 메모리의 데이터는 쉽게 손실 될 수 있다. 데이터를 영속적으로 저장할 수 있는 하드웨어와 소프트웨어가 필요하다. 저장장치는 모든 시스템에 필수적이다.
- 하드웨어는 입출력 혹은 I/O 장치 형태로 제공된다. 요즘에는 solid-state drives(SSDs)가 많이 사용되고 있기는 하지만 장기간 보존할 정보를 저장하는 장치로는 일반적으로 하드 드라이브(hard drive)가 사용된다.
- 디스크를 관리하는 운영체제 소프트웨어를 파일 시스템(file system)이라고 부른다. 파일 시스템은 사용자가 생성한 파일을 시스템의 디스크에 안전하고 효율적인 방식으로 저장할 책임이 있다.
- CPU나 메모리 가상화와는 달리 운영체제는 프로그램 별로 가상 디스크를 따로 생성하지는 않는다.
- open(), write(), close 같은 시스템콜은 운영체제에서 파일시스템이라고 불리는 부분으로 전달된다. 파일 시스템은 요청을 처리하고 경우에 따라 사용자에게 에러코드를 반환한다.
- 운영체제는 시스템콜이라는 표준화된 방법으로 장치들을 접근 할 수있게 한다. 운영체제는 표준 라이브러리 처럼 보이기도 한다.
- 대부분의 파일 시스템은 성능향상을 위해 응용프로그램들이 요청한 쓰기 요청들을 모아서 한번에 처리한다. 응용프로그램 입장에서는 요청한 쓰기의 내용들이 실제로 저장장치에 기록될 때까지 일정시간의 지연이 발생하는 것이다. 여러 문제가 발생할 수 있는데, 디스크에 기록하려고 모아놓은 내용 중 일부가 이미 디스크에 쓰였을 수도 있고, 기록 순서가 뒤 바뀔 수도 있다. 쓰기 중에 시스템의 갑작스런 고장에 대비해서 많은 파일 시스템들이 저널링(jouraling)이나 쓰기-시-복사(copy-on-write)와 같은 기법을 사용한다. 이 기법들은 고장이 발생하더라도, 시스템을 정상 상태로 복구 될 수 있게 한다.
설계 목표
- 가장 기본적인 목표는 시스템을 편리하고 사용하기 쉽게 만드는데 필요한 개념(abstraction)들을 정의하는 것이다.
- 운영체제의 설계와 구현에 중요한 목표는 성능이다. 다른 말로 표현하면 오버헤드를 최소화 하는 것이다.(minimize the overhead)
- 오버헤드는 시간과 공간의 형태로 나타난다.
- 또 다른 목표는 응용프로그램들 간의 보호, 그리고 운영체제와 응용프로그램간의 보호이다. 그리고 운영체제와 응용프로그램간의 보호이다. 운영체제는 한 프로그램의 악의적인 또는 의도치않은 행위가 다른 프로그램에게 피해를 주지 않는다는 것을 보장해야 한다. 보호는 운영체제의 원칙 중 하나인 고립(isolation) 원칙의 핵심이다. 프로세스를 다른 프로세스로부터 고립시키는일은 보호의 핵심이고 운영체제가 해야 하는 일중 많은 부분의 근간이 된다.
- 운영체제는 계속 실행되어야 한다. 운영체제가 실패하면 그 위에서 실행되는 모든 응용 프로그램도 실패하게 된다. 이러한 종속성 때문에 운영체제는 높은 신뢰성(reliability)을 제공해야 한다.
- 시스템의 목적에 따라, 운영체제는 다른 목표를 지향하게 되고, 구현이 달라진다.
배경 소개
라이브러리를 넘어서 : 보호
- Atlas 컴퓨팅 시스템에 의해 시스템콜이라는 아이디어가 발명되었다. 운영체제와 일반 라이브러리가 구분되는 사건이다.
- 시스템 콜과 프로시저 호출의 결정적 차이는 시스템 콜은 제어를 운영체제에게 넘길 때 하드웨어 특권 수준(hardware privilege level)을 상향 조정한다는 것이다. 사용자 응용프로그램은 사용자 모드(user mode)라고 불리는 상태에서 실행된다. 사용자 모드에서는 응용프로그램이 할 수 있는 일을 하드웨어 적으로 제한한다.
- 시스템 콜은 보통 trap이라고 불리는 지정된 트랩 핸들러 함수에게 제어권을 넘기고 특권 수준을 커널모드(kernel mode)로 격상시킨다. 트랩 핸들러 함수는 운영체제가 미리 구현해 놓는다. 커널모드에서 운영체제는 시스템의 하드웨어를 자유롭게 접근할 수 있으며, 입출력 또는 메모리 할당과 같은 작업을 할 수 있다.
- 운영체제가 서비스를 완료하면 return - from - trap 특수 명령어를 사용하여 제어권을 다시 사용자에게 넘긴다. 이 명령어는 응용프로그램이 출발했던 지점으로 제어권을 넘기는 동시에 사용자 모드로 전환한다.
백준
10816 숫자 카드2
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
vector<int> card_arr;
int card_num;
cin >> card_num;
for (int i = 1; i < card_num+1; ++i)
{
int tmp;
cin >> tmp;
card_arr.push_back(tmp);
}
sort(card_arr.begin(), card_arr.end());
int m;
cin >> m;
for (int i = 0; i < m; ++i)
{
int tmp;
cin >> tmp;
cout << upper_bound(card_arr.begin(), card_arr.end(),tmp) - lower_bound(card_arr.begin(), card_arr.end(), tmp) << " ";
}
return 0;
}
- upper_bound와 lower_bound를 쓰면 쉽게 풀 수 있다.
- 위 함수들의 개념을 잘 이해하고 있어야한다.
- 12345667 일때 upper_bound( , ,4) 는 4의 값을 반환하고, lower_bound는 3의 값을 반환하기 때문에 둘의 차이를 구하면 그 숫자의 개수가 된다.
KEYWORD
소켓/소켓 API
소켓 API
- 정의
- System call API 중 하나이다.
- 운영체제가 응용프로그램에게 제공하는 통신용 인터페이스다.
- 역할
- 컴퓨터 하드웨어의 네트워크 통신장치를 응용프로그램이 간접적으로 이용할 수 있게 해준다.
소켓
- 정의
- 응용프로그램에 설치하는 데이터 송수신 출입구
- 사용하는 이유
- 응용프로그램은 응용프로그램의 일만 처리하도록 하기 위해서 사용한다. 응용프로그램이 데이터 송수신을 위한 각종의 일을 직접 수행할 필요가 없다.
- 통신의 업무는 운영체제의 네트워크 스택이 해준다.
- 네트워크 스택이 하는 일
- 데이터의 패킷화
- 주소 지정
- 라우팅
- 전송 오류 처리
- 네트워크 스택이 하는 일
- 컴퓨터가 데이터들을 송수신할 때, 꼬이지 않게 해준다.
- 컴퓨터 내에서 실행되는 다양한 프로세스가 엄청난 양의 데이터 송수신을 일으키는데, 운영체제에 의해 데이터 송수신이 관리되면 다양한 문제를 해결할 수 있다. 그래서 운영체제는 응용프로그램에게 통신시 사용할 수 있는 socket API를 제공하여 응용프로그램은 데이터를 보내고 받기만 할 수 있게 한다.
- 어떤 응용프로그램에서 송수신하는 데이터인지 운영체제 측에서 알아야 하는데 이 소켓이 프로세스별 end point로 역할하여 송시신지가 문제없이 관리된다.
소켓 API 사용법
- 소켓 생성
- 통신을 위한 소켓을 생성한다.
int sockfd = socket(domain, type, protocol);
- 인자
- domain
- 프로토콜 주소체계 지정
- IPv4 : ‘AF_INET’
- IPv6 : ‘AF_INET6’
- 로컬 : ‘AF_UNIX’ or ‘AF_LOCAL’
- socket type
- TCP 방식 : ‘SOCK_STREAM’
- UDP 방식 : ‘SOCK_DGRAM’
- protocol
- 프로토콜 지정 인자
- 기본 프로토콜 : 0
- TCP 방식 : ‘IPPROTO_TCP’
- UDP 방식 : ‘IPPROTO_UDP’
- domain
- 반환값
- 생성된 socket에 대한 File Descriptor로, 운영체제에 의해 생성되며, 이후 소켓을 사용할 때 인자 값으로 보내야 한다.
- 소켓 바인딩
- 소켓에 IP주소와 포트 번호를 할당하는 것이다.
- 서버 프로그램에서 주로 사용한다.
bind(sockfd, (struct sockaddr*)&my_addr, sizeoof(my_addr));
- 인자
- socket descriptor
- address
- socket이 바인딩 될 주소(구조체의 포인터)
- IP와 PORT 번호 설정
- address length
- 주소 구조체의 크기 지정
- 연결 수립
- 클라이언트
- connect() : 서버에 연결 요청
- 서버
- listen() : 클라이언트 요청 확인
- accept() : 클라이언트의 연결 요청 수락
//클라이언트 connect(sockfd, (struct sockaddr*)&server_addr,sizeof(server_addr)); //서버 listen(socked, backlog); int new_fd = accept(sockfd, (struct sockaddr*)&their_addr, &addr_size)
- 인자
- listen
- socket description
- 대기 큐의 길이(backlog)
- accecpt
- socket description
- address
- socket이 바인딩 될 주소
- IP, PORT 번호
- address length
- 주소 구조체의 크기 지정
- connect
- socket descriptor
- server address
- listen
- 클라이언트
- 데이터 송수신
- 데이터 송신
- 데이터 수신
send(sockfd, "Hello, world!", data_size, flags); recv(sockfd, buffer, sizeof(buffer), flags); // UDP sendto(sockfd, "Hello, world!", data_size, flags, dest_addr, addr_len); recvfrom(sockfd, buffer, sizeof(buffer), flags, dest_addr, addr_len);m);
- read와 write도 동일한 목적으로 사용 가능하다.
- LINUX에서만 사용 가능하다
- 네트워크 장치를 file로 인식하는 OS 특성상 사용 가능한 system call 함수이다.
- 네트워크 실행 특성을 반영하는 정보를 읽고 쓰기 위해 만들어진 것이 아니기 때문에 기능이 제한적이다.
- 이 때문에, UDP의 경우 반드시 send를 써야 동신이 가능하다.
- 인자
- socket descriptor
- data buffer
- 전송할 데이터를 담고 있는 버퍼이다. 또는 수신된 데이터를 저장할 버퍼의 포인터다.
- data size
- data byte 수
- flags
- 데이터 송수신 동작 제어를 위한 옵션 플래그
- 대상 주소
- UDP의 경우에만, 상대방의 주소정보를 담은 구조체의 포인터
- 주소 길이
- 상대방의 주소 구조체의 크기
- 소켓 닫기
- close 통신 완료 후, 소켓을 닫고 리소스를 해제한다.
close(sockfd);
- 인자
- socket file descriptor
File Descriptor(FD)
- 정의
- 운영체제가 파일, 소켓, 파이프등의 입출력 리소스를 관리하기 위해 생성해내는 비음수의 값이다.
- 프로세스가 각 리소스에 접근하려고 할 때 리소스에 대한 인덱스로 사용된다. 덕분에 프로세스는 리소스의 실제 물리적 위치를 몰라도, 인덱스를 통해 접근이 가능하다.
- 프로세스의 FD 활용
- 리소스 열기
- 프로세스가 open, socket 등의 system call을 사용해 리소스를 열면 운영체제는 해당 리소스에 대한 핸들을 생성하고, 이를 가리키는 파일 디스크립터를 프로세스에 반환한다.
- 리소스 조작
- 프로세스가 read, write, send, recv 등의 system call로 리소스를 조작할 때, fd값을 인자로 운영체제에 제공해야 한다.
- 운영체제는 이 fd를 통해서 해당 프로세스의 fd table에서 리소스를 찾아 요청된 리소스 조작을 수행한다.
- 리소스 닫기
- 프로세스가 close system call로 리소스를 닫아달라 요청할 때, fd 값을 인자로 운영체제에 제공해야 한다.
- 운영체제는 fd table에서 해당 엔트리를 제거하고, 리소스를 해제한다.
- 리소스 열기
File Descriptor talbe
- 정의
- 운영체제의 커널 내부에 각 프로세스별로 fd table이 생성된다.
- 각 프로세스가 열어놓고 있는 모든 파일, 리소스에 대한 fd를 인덱스로 하는 배열이다.
- 각 entry의 구성
- 인덱스
- 리소스별 file descriptor
- 리소스 타입
- 파일, 소켓 ,파이프 중 어떤 것인지 표시
- 리소스 상태 정보
- 읽기/쓰기 가능 여부
- 블록킹/논블록킹 모드
- 열린 파일의 현재 위치
- 리소스에 대한 참조
- 실제 리소스에 대한 포인터
- 인덱스
Defalut File Descriptor
- 정의
- 프로세스가 시작될 때 자동으로 할당되는 기본 fd의 값이다.
- 프로세스가 실행되고 있는 동안은 항상 열려있는 것으로 표시된다.
- 다른 파일이나 리소스는 이 default fd 인덱스 이후 숫자부터 할당된다.
- 이렇게 입출력기가 file descriptor로 관리되는 이유는 OS에서 입출력기도 파일로 인식하여 관리하기 때문이다.
- 종류
- 0 : 표준 입력(stdin)
- 1 : 표준 출력(stdout)
- 2 : 표준 에러(stderr)
HTTP(Hyper Text Transfer Protocol)
- 정의
- 웹 컨텐츠(HTML, 문서, 이미지, 파일 등)를 교환하기 위한 프로토콜
- 어떤 방식으로 데이터를 교환할 지 정해놓은 표준 규칙
- 연결 방식(HTTP 버전별 상이)
- 데이터 전송 방식(Method)
- 데이터 형식(Content - Type)
- 기능
- 다양한 클라이언트 - 웹서버 통신의 효율과 호환성을 높인다.
- 클라이언트 - 서버 간 데이터 통신은 다양한 방식으로 이뤄질 수 있다. 모든 클라이언트와 서버가 각각의 방식으로 데이터를 교환한다면 매번 방식이 달라서 번거롭고 복잡하다. HTTP는 통신 과정에서 모든 클라이언트와 웹서버가 표준적으로 사용할 규칙이다.
- Hyper Text로 분류되는 데이터를 교환하는 데 최적화 되어 있다.
- HTML 문서
- CSS 파일
- JavaScript 파일
- 기타 데이터 타입의 통신도 지원한다.
- Content - Type 헤더를 통해 다양한 미디어 타입을 교환할 수 있도록 지원한다.
- 이 덕분에, 다양한 유형의 데이터 전송이 HTTP 하나만 따르더라도 가능하다.
- 다양한 클라이언트 - 웹서버 통신의 효율과 호환성을 높인다.
- 용도
- 웹 서버 - 웹 브라우저 클라이언트 통신
- RESTful API 통신 : JSON 데이터만 주고받는 통신
- IoT Device 통신 : 웹서버 - IoT Device(사람이 아니라 기기가 자동으로 데이터 통신)
- Web Socket 통신 : HTTP로 소켓 연결 후, 연결을 지속적으로 유지하여 실시간으로 양방향 통신을 실행한다.
- Cloud Service : 클라우드 스토리지, 컴퓨팅, 데이터베이스 - 클라이언트
- Webhooks : 이벤트를 발생시키는 시스템과 이벤트를 수신하여 처리하는 시스템간의 통신이다. 웹 클라이언트가 없이도, 미리 설정해둔 ULR로 HTTP 요청을 자동으로 보내 이벤트를 알린다.
- HTTPS와의 차이
- HTTP방식의 프로토콜에 SSL/TLS를 사용하여 데이터를 암호화한 방식
- HTTP 메시지 구조는 동일하다
- Server쪽에 추가로 구현해야 할 사항이 있다.
- SSL/TLS 인증서 설치
- 서버 설정 : Apache,NginX 등 구성, 포트 443 설정
- 클라이언트와 연결 수립 후, 암호화 알고리즘 설정
- 암호화/복호화를 위한 성능 고려
HTTP에서 정해둔 규칙
- 연결 병식
- HTTP 버전 별로 상이하다
- HTTP/1.1
- 지속 연결(Persistent Connection)
- 하나의 TCP 연결을 통해 여러 요청과 응답을 전송한다
- HTTP/2
- 멀티플렉싱(Multi Flexing)
- 여러 요청과 응답을 동시에 전송 가능하다
- 데이터 전송 방식
- 클라이언트가 데이터를 어떻게 처리할지 서버에게 작업 내용을 알려주는 메세지다
- 각 타입에 따라 서버가 데이터를 다루는 액션이 달라진다
- GET : 리소스 조회
- POST : 리소스 생성
- PUT : 리소스 업데이트
- DELETE : 리소스 삭제
- HEAD : 리소스의 메타 데이터를 빠르게 조회한다.(데이터 없이 메타 데이터만)
- OPTIONS : 해당 서버에서 사용가능한 메소드를 확인한다
- 데이터 형식
- 보내거나 받는 데이터의 형식이다.
- MIME(Multipurpose Internet Mail Extensions) 타입을 사용하여 형식을 규정한다.
- HTML : text/html
- JSON : application/json
- Image : image/png, image/jpeg
HTTP 메시지
- HTTP를 따르는 클라이언트-서버 간 데이터 교환에 사용되는 데이터의 포맷이다.
# HTTP 메시지 예시
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
- 종류
- 요청(Request)
- 응답(Response)
- 구조
- 시작줄(Start Line)
- 요청 메세지
- HTTP method
- 요청 대상(URL)
- HTTP 버전
- GET <http://naver.com> HTTP/1.1
- 응답 메시지
- HTTP 버전
- 상태코드(Status Code)
- 상태메세지(Status Message)
- HTTP/1.1 200 OK
- 요청 메세지
- 헤더(Header)
- 메세지에 대한 메타데이터
- Content - Type : 메세지 본문의 유형(MIME type)
- Content-Length : 메세지 본문의 길이(byte)
- Connection : keep-alive 지속 연결(HTTP/1.1의 기본 값)
- Authorization
- 서버에 대한 클라이언트의 인증정보
- 기본 인증 방식으로 사용
- : username: password 를 BASE64로 인코딩 Basic YWRtaW46cGfzc3lsfQ=
- 베어러 토큰 방식으로 사용
- : OAuth 2.0 토큰 기반 인증 시스템에서 발급 받은 토큰 넣기 Bearer access_token_from_oauth
- 빈 줄(Empty Line)
- 헤더와 본문 구분
- 본문(Body)
- 실제 전송하려는 데이터
- 메소드나 상태에 따라 본문이 없을 수 있다.
- 시작줄(Start Line)
728x90
'Study > TIL(Today I Learned)' 카테고리의 다른 글
24.02.27 퀴즈, 간단한 정리, 백준, KEYWORD (2) | 2024.02.28 |
---|---|
24.02.26 간단한 정리, 백준 (2) | 2024.02.27 |
24.02.24 간단한 정리, 백준, KEYWORD (1) | 2024.02.25 |
24.02.23 CSAPP, 백준, KEYWORD (0) | 2024.02.24 |
24.02.22 백준,KEYWORD (1) | 2024.02.23 |