컴퓨팅에서 심볼릭 링크(symbolic link) 또는 기호화된 링크는 절대 경로 또는 상대 경로의 형태로 된 다른 파일이나 디렉터리에 대한 참조를 포함하고 있는 특별한 종류의 파일이다.
심볼릭 링크는 대부분의 작업에 투명하게 동작한다. 심볼릭 링크로 이름이 지정된 파일에 읽고 쓰는 프로그램들은 마치 운영 체제가 직접 대상 파일에 작용하는 것처럼 수행한다. 그러나 심볼릭 링크들을 특별하게 다루어야 하는 프로그램들(이를테면 백업 유틸리티)은 이들을 직접 식별하고 조작할 수도 있다.
심볼릭 링크는 다른 파일이나 디렉터리에 대한 경로로서 운영 체제가 자동으로 해석하고 추적하는 텍스트 문자열을 포함한다. 이러한 다른 파일이나 디렉터리를 대상(target)으로 부른다. 심볼릭 링크는 대상으로부터 독립적으로 존재하는 두 번째 파일이다. 심볼릭 링크가 삭제되면 대상은 영향을 받지 않는다. 심볼릭 링크가 대상을 지시하면 나중에 대상이 이동되거나 이름이 바뀌거나 지워지더라도 심볼릭 링크는 자동으로 업데이트되거나 삭제되지는 않지만 지속적으로 오래된 대상(현재는 존재하지 않는 위치나 파일)을 가리킨 채로 존재한다. 이동되었거나 존재하지 않는 대상을 가리키는 심볼릭 링크들은 broken, orphaned, dead, dangling 등의 용어로 불리기도 한다.
심볼릭 링크는 하드 링크와는 차이가 있다. 하드 링크는 다른 볼륨이나 파일 시스템 상의 경로를 연결하지 않지만 심볼릭 링크는 링크와 대상이 존재하는 볼륨의 어느 파일이나 디렉터리라도 가리킬 수 있다. 하드 링크는 무조건 기존의 파일만을 가리키는 반면 심볼릭 링크는 어느 것을 가리키지 않는 임의의 경로를 포함할 수도 있다.
파일 시스템 계층을 재정렬하려는 노력에 따라 일부 유닉스와 리눅스 배포판들은 심볼릭 링크를 널리 사용한다. 이는 변종의 콘텍스트 의존 심볼릭 링크들과 같은 일부 매커니즘을 통해 수행할 수 있다. 또, 더 직관적이거나 응용 프로그램에 특화된 디렉터리 트리를 만들고, 핵심이 되는 시스템 명령 및 유틸리티들을 다시 설계하는 일 없이 시스템을 다시 정리하는 기회를 제공한다.
◈ 유저 프로그램에서 뭔가 중요한 작업(직접적인 하드웨어 접근, 중요한 시스템 요청)이 있을때 커널 모드로 전환하게 된다
◈인터럽트를 통해 시스템 요청이 커널로 전달된다
시스템 호출 SystemCall 이 소프트웨어 인터럽트를 통해 커널 모드로 진입한다는 의미이다
시스템 콜 이라는 것 자체가,
사용자 프로그램이 디스크 파일에 접근하거나 수행결과를 화면에 출력하는 등의특권 명령이 수행할 필요가 있을때, 운영체제에 인터럽트를 걸어서 특권명령을 대행해줄 것을 요청하는 것을 말한다.
그러니깐, "하던거 그만 두고 내 명령좀 실행해줘!!" 쯤 되는 것 같다
애초에 인터럽트가 함수 호출이랑 비슷해서,
어떤 프로그램이 CPU를 할당 받아 명령을 수행하고 있는데, 인터럽트가 발생하면 그 프로그램은 수행중이던 명령어의 위치를 PCB(하드웨어 제어 블록)에 저장한다
인터럽트가 영어로 뜻이 Interrupt 인데, 실제로 그 "방해하다"의 뜻이 맞다!!
2)커널 모드 (이름만 들어도 중요할거같은 느낌... 팍... 커널에 대해서는 지난 번에 공부했으니)
◈ 모든 시스템 자원에 접근이 허가된 모드
유저모드, 커널 모드 개념도 정리
시스템 호출이란?
프로그램의 요청에 따라 커널에 접근하기 위한 인터페이스
- 사용자 모드에 있는 유저 프로그램이 커널 기능을 요청할 수 있도록 함
- 시스템 호출을 하면유저 모드에서 커널 모드로 전환
- 시스템 호출이 모두 처리 되면다시 커널 모드에서 유저 모드로 돌아온다
시스템 호출 유형
프로세스 제어(Process Control) - fork, exit, wait
파일 조작(File Manipulation) - open, read, write, close
장치 관리(Device Management) - ioctl, read, write
정보 유지(Information Maintenance) - getpid, alarm, sleep
통신(Communication) - pipe, shm_open, mmap
보호(Protection) - chmod, unmask, chown
scanf 함수의 read시스템 호출 과정
#include <studio.h>//전처리기, 헤더파일 추가, 헤더파일 int main(void)//메인 함수, 프로그램의 시작점이며 프로젝트에 하나만 존재한다{//함수의 시작 int num;scanf("%d",&num);//num에 입력받은 d값을 넣는다, &는 그값의 주소를 알려줌return0;//반환값}//함수의 끝
※ 참고))
printf는 그냥 변수 값만 받는데 scanf는 변수의 주소가 필요한 이유
- scanf는 num이라는 변수 자체를 이용하지 않는다. scanf 내부에 다른 변수를 선언하여 그 변수에 num값을 대입하고, 대입한 값을 이용해 변수를 출력하기 때문에, num 값을 바꾸다 보면 문제가 될 수 있어서!
예를 들어))
int num =3; int result =add(num);printf("num = %d, result = %d", num, result);
1) add함수가 변수 값을 받아 사용할때 → num = 3, result =4
2) add함수가 변수를 직접 사용하는 경우 결과 → num = 4, result = 4
작성하는 사람 입장에서는 1)을 생각하지만
add()함수의 경우 내부에서 어떻게 변할지를 모른다
그렇지만, 경우에 따라서 num값을 실제 받은 값으로 바꿔야 하는 경우라면
(필요한 경우)변수의 주소를 값으로 넘겨주어 처리하여 직접 변수에 접근해서 변수의 실제 값을 바꾸는 것!!
그래서 scanf는 변수 주소값을 인자로 받는다
정리))
특정 함수에 변수들이 들어가서 값이 이리저리 바뀌다 보면 어떤 값이 튀어나올지 모르는데,
사용자 입장에서는 내가 넣어준 "그 값"으로 계산하고 싶을 때가 있을거다
그럴때!!! 변수의 주소를 불러와서 이용하게 되므로,,,,,
scanf는 변수 주소값을 인자로 받는다!
scanf 자체가 주어진 문자열 스트림 소스에서 지정된 형식으로 데이터를 읽어내는 기능임!!
scanf에 대해 더 알아보자
scanf는 c표준 라이브러리에서 제공하는 함수이다
참고로 헤서에 있는 <studio.h>는 표준 입출력 라이브러리의 약어인데,
C언어의 표준 라이브러리 함수의 매크로 정의, 상수, 여러 입출력 함수가 포함된다
→ 그러니, scanf도 여기에 포함되는 함수 중 하나인 것!
리눅스에서는 GNU C library(glibc)가 C 표준 라이브러리를 구현한다
전에 알아보았던 glibc로 알려진 GNU프로젝트가 구현한 표준 라이브러리이다
GNU 시스템과 리눅스 시스템에서 사용하는 대표적인 c 라이브러리라고 보면 된다
키보드, 텍스트 파일 등 각종 파일들로부터 데이터를 읽어오기 위해서 read()함수를 호출한다
strace 도구를 사용하면, 프로그램에서 요청(Call)하는 시스템 호출 목록을 볼 수 있는데
scanf 호출 시에는 read()함수가 불리는 것을 볼 수 있다
read()함수는 read 시스템 호출의 wrapper함수로 read 시스템 호출 콜이다
다시 말하지만, 시스템 콜의 종류는 크게 6가지이고 해당 종류들은 아래와 같이 있으니, read()도 그 중의 일부라고 보면 된다
프로세스 제어(Process Control)
fork()
exit()
wait()
파일 조작(File Manipulation)
open()
read()
write()
close()
장지 조작(Device Manipulation)
ioctl()
read()
write()
정보 유지(Information Maintenance)
getpid()
alarm()
sleep()
통신(Commnication)
pipe()
shm_open()
mmap()
보호(Protection)
chmod()
umask()
chown()
wrapper 함수라는 것은,
말그대로 뭔가를 wrapping 해주는 함수이다. 감싼다는 말인데,
예를 들어, C언어로 만들어진 라이브러리를 C++과 같은 클래스 형태로 사용하고자 할때,
한번 감싸주는 것이 wrapper 함수이다.
그러니, 다른 함수를 자신으로 감싸는 녀석이라고 보면 된다.
그리고 당연하게도, 본래 함수의 기능 잃지 않은 상태여야 하는 것이다
그렇기 때문에
read() 함수는 read 시스템 호출의 wrapper 함수로써 read 시스템 호출 콜
이 말은,
read()함수는 read 시스템 콜을 감싸는 녀석으로 read시스템 콜의 기능을 하는 것이다
1)warpper를 통한 시스템 호출
① 시스템 호출과 일대일로 대응되는 wrapper 함수가 존재한다.
② 어셈블리로 소프트웨어 인터럽트를(0x80)를 발생시켜야 시스템 호출이 발생하는데, wrapper함수가 이를 대신한다
인터럽트 함수의 특징 => 인터럽트가 발생했을 때 커널이 호출하고, 인터럽트 컨텍스트 (interrupt context)라는 특별한 컨텍스트에서 실행된다
※ 참고))
이쯤되면 인터럽트와 시스템 콜이 굉장히 헷갈린다
둘이 뭐가 다르고, 공통점은 뭐고, 뭐가 다른데??
실제로 이 질문을 하는 사람이 굉장히 많은 것을 볼 수 있었다
나도 정리하여 모아봤다
일단 기본적으로, 프로세서는 명령어를 하나씩 실행하게 되는데
가끔씩 프로세스가 일시적으로 멈추고, 현재 명령어를 미루고
다른 프로그램이나 코드 세그먼트(다른 곳에 상주)를 실행해야 하는 경우가 있다
이런 경우 프로세스는 정상 실행으로 돌아가고 중단된 부분부터 계속 된다
맥락이 끊긴다고 봐야하나...하던걸 멈췄다가 다시 실행하는 거다
시스템 호출과 인터럽트가 그런 경우이다
시스템 호출 = 시스템에 내장 된 서브 루틴 호출, 운영체제(커널)의 서비스를 호출하여 사용
또 모르는 용어가 나왔는데, 서브 루틴이다
프로그래밍 시 매크로(macro)가 자주 쓰이는데, 매크로는 자주 반복되는 명령어를 묶어서 하나의 이름으로 만드는 것이다
프로그래밍 시 매크로를 사용하는 부분은 매크로의 원문으로 모두 대체되어 소스코드의 크기가 커지고, 메모리 점유율이 높아진다.
그래서, 이러한 매크로의 단점을 극복하고 반복되는 것을 한번만 써서 메모리 사용을 최대한 줄이도록 한 것이 서브 루틴이다.
반복되는 특정 기능을 모아서 이름을 붙인 기능은 매크로와 같지만, 프로그램의 흐름이 메인 루틴에 있지 않고 별도의 공간에 한번만 생긴 것이 다르다
따로 빼서 기능을 모아둔거...... 라고 생각하려고 한다
인터럽트 = 외부(CPU 외부) 하드웨어 이벤트로 인한 프로그램 제어 인터럽트
컴퓨터가 정상적으로 실행되는 동안 CPU가 일시적으로 중단되는 이벤트가 발생할 수 있는데, 이것이 인터럽트이다.
1) 하드웨어 인터럽트 = 인터럽트
2) 소프트웨어 인터럽트 = 예외 또는 트랩
인터럽트 발생 시 ISR (인터럽트 서비스 루틴)이라는 특수 서브 루틴으로 전송
ISR (인터럽트 서비스 루틴) : 인터럽트 핸들러와 마찬가지로
인터럽트를 처리하기 위해 커널이 실행하는 함수
그래서, 시스템 호출과 인터럽트의 차이점은?
시스템 호출 = 시스템에 내장된 서브 루틴 호출
인터럽트 = 프로세서가 일시적으로 현재 실행을 보류하게 하는 이벤트
이므로
→
시스템 호출은 프로그래머에 의해 고정된 시간에서 발생하지만
인터럽트는 사용자가 키보드를 누르는 것과 같은 예기치 않은 이벤트로 인해 발생
말그대로 인터럽트는 의도치 않게 interrupt 받는거고
시스템 호출은 의도적으로 특정 시간동안 호출 하는것
시스템 호출은 프로세서는 어디로 돌아갈 지만 기억 하면 되지만
인터럽트는 프로세서가 시스템을 되돌릴 장소와 시스템의 상태를 기억해야하고,
현재 프로그램과 관련이 없다(의도치 않은거니깐!!!!)
그러면, 서브루틴을 호출하기 전에 메인루틴에서 어떻게 서브 루틴 종료 후 다시 돌아올 주소값을 저장할 수 있을까?
CALL 명령어를 이용해 서브 루틴(func 함수)을 호출할 시에
CALL 명령어 다음에 메모리 주소를 스택에 저장한다
이 후 서브 루틴의 기능을 수행하고 RETN 명령어를 만나면 현재 ESP레지스터가 가르키고 있는 스택값을 읽는다(ESP가 가르키는 곳에 메인루틴의 CALL 명령어 다음의 주소가 저장 되어 있다)
1. 프로그램에 함수 호출이 발생한다.
2. 스택 프레임이 생성되고 콜 스택에 푸시된다. 스택 프레임은 다음과 같이 구성된다:
1) 함수가 종료되면 복귀할 주소
2) 함수의 모든 매개 변수
3) 지역 변수
4) 함수가 반환할 때 복원해야 하는 수정된 레지스터의 복사본
여기서 스택 프레임은, 스택에 차례대로 저장되는 함수 호출 정보를 말한다.
3. CPU가 함수의 시작점으로 점프한다.
4. 함수 내부의 명령어를 실행한다.
5. 그 이후엔
1) 레지스터가 콜 스택에서 복원된다.
2) 스택 프레임이 콜 스택에서 튀어나온다. 이렇게 하면 모든 지역 변수와 매개 변수에 대한 메모리가 해제된다.
3) 반환 값이 처리된다.
4) CPU는 반환 주소에서 실행을 재개한다.
2)syscall 함수를 통한 시스템 호출
① insyscall(int number, ...);
② number는 호출하려는 시스템 호출 번호이며 그 뒤는 가변 인자를 뜻한다
③ wrapper 함수와 마찬가지로 시스템 호출을 대신해주는 역할을 가짐
- 차이점은 모든 시스템 호출을 syscall이란 한 함수로 가능하게 함
- Wrapper 함수가 등록되지 않은 시스템 호출 역시 syscall 함수로 호출 가능
- 시스템 호출 번호는 매크로로 등록되어 있으며 Read 호출 번호 매크로는 SYS_read
인터럽트 함수의 특징 => 인터럽트가 발생했을 때 커널이 호출하고, 인터럽트 컨텍스트 (interrupt context)라는 특별한 컨텍스트에서 실행된다
- y (Yank) : 복사하기 - yy : 한 줄 전체의 내용을 복사한다 - 2yy : 두줄복사 - nyy : 현재 줄 이하로 n개의 줄을 복사한다 (n은 임의의 숫자, 2yy는 2줄 복사) - ynw : n개의 단어를 복사한다(y2w는 두 개의 단어를 복사) - yw : 한단어 복사 - y2w : 두단어 복사 - y$ : 현재 위치에서 그 줄의 끝까지 복사한다 - y0(y^) : 현재 위치에서 그 줄의 처음까지 복사한다 - yG : 현재 위치에서 파일의 끝까지 복사한다(G는 파일의 마지막 줄) - Y : 한 줄 전체의 내용을 복사한다 (yy 와 동일) ※ 마지막 명령어의 반복 - . : 마지막에 수행한 명령어를 반복한다. -2. : 명령어를 2번 반복한다.
붙이기
- p (Put or Paste) : 붙이기 - p : 버퍼에 저장된 내용을 커서의 오른쪽으로 붙여 넣는다. - 2p : 아래로(오른쪽으로) 두번 붙이기 - np : n번만큼 p 명령을 반복. 2p라면 버퍼의 내용을 두 번 붙여넣는다 - P : 위로(왼쪽으로) 붙이기 - 2P : 위로(왼쪽으로) 두번 붙이기 - nP : 버퍼에 저장된 내용을 커서의 왼쪽으로 붙여넣는다. 사용법은 p와 같다
합치기
- J(Join) : 여러 줄의 내용을 한 줄로 합친다 - J : 현재줄을 윗줄에 붙인다. (두줄 합치기) - nJ : n개의 줄을 합쳐 한 줄로 만든다. 커서는 원본 문서의 마지막 줄의 첫번째 위치(합쳐진 줄에서는 중간)에 놓인다. 5J는 5줄로 이루어진 내용을 한 줄로 만든다
다른파일 삽입|병합|하기: Insert merge file
- r test.txt
- r /경로/test.txt
복구하기
- u (Undo) : 되살리기 명령으로 버퍼에 저장되어 있는 원래의 내용을 복구 - u : 한번복구하기 - 'nu' : (n은 임의의 숫자) 형식으로 사용하며, n 단계까지의 명령을 복구할 수 있다 - 2u : 두번복구하기 -Ctrl +r == REDO