ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리눅스, 명령어, FD, 디버깅방법 - 시스템프로그래밍을 위한 리눅스기본
    시스템프로그래밍 - 리눅스 2022. 12. 14. 09:33
    728x90
    반응형

     

    OS = Kernel = 리소스 관리자//리소스는 한정되어있어서 관리가 필요하다

     

    리눅스

    (전세계 500만명이 연구개발중/반도체벤더들도 연구개발중)(리눅스는 오픈소스를 좋아함)

    오픈소스는 회사에서 써도 문제가없지만 프리소프트웨어는 상용제품으로 만들면 문제가 될수있음.(라이센스부분)

     

    리눅스 명령어

     

     .*  맨 앞에 .이 붙은 파일들은 숨김파일이다.
     ~ 홈디렉터리 약자(홈디렉토리란 현재 자기 자신의 계정이 위치한 디렉토리를 의미한다.)
     ., ..  파일 중에 '.'과 '..' 이라는 희얀하게 생긴녀석들이 있다.
    '.'은 현재 자기 자신을 나타낸다 (C++의 this라고 생각하면 됨)
    '..'은 상위 디렉토리,즉 부모를 나타낸다.
     명령어
     clear  화면을 깨끗하게 해준다.
     ls

    • list의약자 현재디렉토리에 어떤 디렉토리가 있는지 나타내준다.
    • ls -a라는 옵션을 줘서 구동시킬 때만 이 숨김파일들을 볼수 있다.
    • ls -l이란 옵션을 줘서 구동할 경우 파일 혹은 디렉토리의 주인이 누구인지 알 수 있고 권한등을 확인 할 수 있다.
    • 파일이나 디렉토리의 권한에 대해서는 좀더 추후에 sticky bit, setuid, setgid를 살펴보면서 확인
    • ls -al이란 옵션을 줄 경우엔 숨김 파일을 포함하여 권한등을 살펴볼 수 있다.
    • ls 명령어를 쳤을 경우 색깔이 초록색이면 실행파일, 파랑색이면 디렉토리, 흰색이면 그냥 파일

     mkdir

    • make directory의 약자로 디렉토리를 만드는 명령어다.
    • 'mkdir 디렉토리명'의 방식으로 사용하면 된다.

     cd

    • change directory 의 약자로 디렉토리를 이동하는 명령어다
    • 'cd 경로'의 방식으로 사용하면 된다
    • 여기서 경로라는 것이 굉장히 애매한데 절대경로와 상대경로라는 것으로 나뉘게 된다
    • 절대경로의 경우에는 디렉토리 위치를 맨 처음에 마운트된 '/'일명 루트 파일 시스템에서부터
    • 디렉토리를 기술하여 경로를 적어주면 되고,
    • 상대경로의 경우에는 현재 위치에서 상대적인 위치를 표기해주면 된다.

     pwd

    • 약자는 PassWord인데 굉장히 애매한 명령어다
    • 현재 사용자가 어떤경로에 있는지 보여주는 명령어다. 그냥 입력하면 된다.
    • 'pwd'를 입력할 경우 '/home/계정이름'으로 나타나는 것을 볼 수 있을 것이다.
    • 예로 /home/kwrg가 있다고 하면 아래와 같이 해석하면 된다.
    • 맨 앞의 '/'는 무조건 루트파일 시스템으로 생각하도록 한다.
    • 그 후의 '/'들은 그냥 구분자로 사용한다.
    • 즉, 사용자가 있는 현재 경로는 루트파일 시스템 밑에 home디렉토리 밑에 (userName)디렉토리라고 해석하면 된다.

     cp

    • CoPy 명령어의 약자
    • 결국 현재 예제에서 만든 것이 cp명령어를 구현한 것과 같다.
    • 사용방법은 이와 같이 사용할수 있다. cp '파일이름1' '파일이름2' 



    sudo apt-get update
    sudo apt-get install vim




    vi라는 편집기가 존재한다.
    이것을 보다 기능을 확장하고 편의성을 제공해 줄수 있도록 vim으로 업그레이드 한 것이다.
    이제 vim을 활용하여 실질적인 프로그래밍을 해보도록 한다
    vim에는 명령모드와 입력모드와 그 외의 한 가지 모드가 더 존재한다.
    우선 명령 모드와 입력 모드 두가지를 파악하면 작업이 수월하다.


    vi라는 명령어를 그냥 이용하면 알아서 vim이 동작하도록 위에서 작업했다.
    그러므로 아래와 같이 사용하면 된다.


    vi '만들고자 하는 파일명'


    ex) vi test.c
    vi vector.h
    vi matrix.cpp 등등


    편집기를 동작시키게 되면 기본적으로 명령 모드로 동작하게 된다
    명령 모드에서 입력 모드로 변환을 수행하기 위해 네가지 정도의 기능을 활용할 수 있다.


    i, a, Shift + I, Shift + A


    각각의 용도는 추후 설명하도록 하고 이 네가지중 편한거 아무거나 사용하도록 한다.


    그러면 아래쪽에 Insert가 보일텐데 이때부터 입력을 시작하면 된다.
    반드시 Insert가 나타난 이후에 입력을 시작해야 한다.
    그리고 입력이 완료되면 ESC키를 눌러서 입력 모드를 명령 모드로 바꿔주도록 한다.




    명령모드로 돌아온 상태에서
    ':w + enter' 는 저장하기
    ':q + enter' 는 나가기
    ':q! + enter' 는 강제종료
    ':w! + enter' 는 강제저장
    ':wq + enter' 는 저장하고 나가기 <<이걸쓴다.
    ':wq! + enter' 는 는 강제저장 및 나가기

    gcc

     

     gcc : GNU Compiler Collection 의 약자로 컴파일러 모음이다.
    C, C++, Java, Go, Ada, Fortran등 여러 언어들을 컴파일 할 수 있다.


    사용방법은 여러가지가 있는데 우선 가장 간단한 방법은 'gcc 컴파일할 파일명'으로 사용하는 것이다
    이렇게 할 경우 실행 파일의 이름이 'a.out'으로 생성된다
    이렇게 만들어진 실행 파일을 동작하고자 한다면 아래와 같이 한다.
    './파일명' 이름이 'a.out'이니 './a.out'으로 구동하는 것이다.


    이제 실행 파일 이름 자체를 원하는 형태로 만들어볼 수 있다.
    gcc -o '만들고싶은 실행 파일명' '컴파일 할 파일 명'


    ex) gcc -o test test.c
    gcc -o proj test.c


    위의 2개 예에서 각각 실행은 아래와 같이 하면 된다는 것을 알 수 있을 것이다.
    './test' 혹은 './prog'으로 실행하면 된다.

     

     

    "Unix는 모든 것을 파일로 관리한다." 라는 핵심 철학을 가짐.

    open()

    파일설명을 위한 예제시스템콜 자세한건 나중에

    open(파일명, 동작조건, 권한) 혹은 open(파일명, 동작조건)
    open이란 녀석은 Kernel(OS)내부에 FD(File Descriptor)라는 객체를 내부에 생성하게 된다.
    이후의 동작들은 이 FD를 기반으로 read, write, close, lseek등의 동작들을 수행할 수 있게 된다.
    좀더 상세한 것은 그림으로 그리도록 한다.
    open의 반환 값은 Kernel에서 생성한 FD배열의 index다.
    윈도우 API를 공부했다면 HANDLE과 같은 개념이다


    O_CREAT : 파일을 생성하라는 의미
    O_RDWR  : 파일 자체에 read, write를 모두 가능하게 하겠다는 의미
    O_RDONLY
    O_WRONLY
    O_TRUNC : 파일을 비우라는 뜻.(항상 새파일이 된다)
    O_EXCL  : 파일이 존재하면 새로 만들지 않는다!(-1리턴)


    권한에 해당하는 0644는 나중에

     

     

    기존에 C 언어를 사용하면서 봤던 함수들을 포함해서

    대다수의 Library기능에 들어있는 모든 함수들은 System Call이다.

     

     리눅스 코드 구조

     리눅스 코드 구조(file_struct와 task_struct 관련)
     sys_read
    task_struct
    signal_struct
    mm_struct
    files_struct
    file ** 
    path
    dentry
    inode
    super_block

     

     

     FileDescriptor(fd)

     FileDescriptor(fd)
    fd_array[0] 표준입력
      [1] 표준출력
      [2] 에러
    //여기까지 기본
      [3] <-파일생성시 리턴값.
    file_io2.c 코드에서 if문 {~~~} 아래쪽에
    printf("filedes = %d\n", filedes);를 추가한다.
    그러면 3이 출력될 것임.


    결국 이 철학이 얘기하는 것은 HW도 파일로 관리한다는 것이다.
    그렇기 때문에 디바이스 드라이버를 만들 때 파일 작업을 하게 된다. 

     

     read()시스템콜

     read()시스템콜
     read(fd, buf, size)
    여기서 fd란 
    Kernel내에 task_struct 구조체 밑에 있는 files_struct 밑에 있는 file 구조체에 대한 배열 포인터의 index다.
    0, 1, 2는 표준 입력, 표준 출력, 표준 에러로 부팅시에 설정되고
    이 후 사용자가 open()을 이용할 때마다 3번부터 fd를 할당해준다.


    중요한것은 open()으로 얻은 이 번호를 read, write등의 연산에 활용한다는 것이다.
    활용할 때 메커니즘은 fd번호를 알고 있으니 read()를 통해서 
    "Kernel아 fd에 있는 내용을 읽어줘~"라고 요청하는 것이다.


    read(fd, buf, size) 였는데 fd의 용도는 위와 같고
    buf에는 fd를 통해 실제 파일에서 읽은 내용을 buf에 저장한다
    뒤쪽에 있는 size를 통해서 buf에 얼마만큼의 크기를 저장할지를 경정한다.


    예로 read(fd, buf, 64)고 실제 파일의 데이터가 100 byte라면
    buf에는 64 byte 만큼만 옮겨지고 나머지 36byte는 옮겨지지 않는다.
    쉽게 생각하면 fd -> buf방향으로 데이터가 이동하는 것이다.


    write 역시 마찬가지인데 방향은 반대다.
    fd <- buf로 버퍼에 들어간 정보가 fd로 이동한다고 보면 된다.
    즉, string 자체를 fd로 넘겨버려도 된다는 뜻이다.


    read와 write의 return값(반환값)은 몇 byte를 읽었는지 혹은 몇 byte를 썼는지의 숫자값을 반환한다.


    write(fd, buf, size)




    표준 입력 : 0
    출력 : 1
    에러 : 2


    read(0, buf, size) = scanf()

     

     리눅스 디버깅방법

     리눅스 디버깅방법
     gcc -g <- 디버깅
    gdb a.out <- 디버깅시작


    gdb) shell 리눅스명령어
    r 디버깅 실행 ( r 인자)로 인자를 줄수있다.
    b main 메인함수에 브레이크포인트를 걸겠다
    disas 어셈블리어로 보겠다.
    n 다음줄(F10)
    s (F11)
    p argc argc값 조사
    c continuing
    q 종료
    bt 현재 콜스택을 볼수있다.
    info register 레지스터를 볼수있다.
    p $eax eax만 보겠다.
    p/x $rcx 16진수로 보겠다.
    l 코드를 보겠다.
    x 0x번지수 번지수의 값을 보고싶다.
    x/c 0x번지수 번지수의 값을 캐릭터형식으로 보고싶다.

     

     

    /////////부록

    tar <- 압축을 해제하는 명령어

    tar->여러개의 파일을 묶는 작업..

     

     

    System Call은 User가 Kernel에게 요청하는 작업을 의미한다.

    warning -> #include <unistd.h>

     

    728x90
    반응형

    댓글

Designed by Tistory.