시스템 : 구성 요소들이 상호작용하는 집합체
컴퓨팅 시스템 : CPU, 기억장치, 입출력장치 등이 상호작용을 하는 집합체
임베디드 시스템 : 컴퓨팅 시스템 중, 전용기능(특정목적)
을 수행하도록 만들어진 시스템
API : APP Level에서 사용하는 함수, Library : API 모음집
시스템 콜
: 리눅스에서 APP이 커널의 기능을 쓸 수 있도록 만든 API , POSIX와 Therad Programming으로 개발
시스템 프로그래밍 : OS가 제공하는 API를 이용한 프로그래밍
시스템콜(syscall) : 리눅스
에서의 시스템 프로그래밍
win32 API : 윈도우
에서의 시스템 프로그래밍
펌웨어(F/W) : OS 없음
POSIX : Application 개발자들을 위해 OS마다 제공되는 API들이 하나로 통일된 API
여러 임베디드 OS에서도 편리하게 APP 개발 가능하다.
과거 : APP/OS/HW 모두 매번 새로 개발하여 제작하였습니다.
현재 : 기존에 만들어진 틀을 이용하여 Firmware와 HW만 새로 개발합니다.
리눅스 APP
이 리눅스 커널
에게 어떤 부탁
을 하기 위해 만들어진 API
High Level API(= Wrapper 함수) : printf, scanf, fopen() 등
Low Level API : open(), 시스콜
리눅스에서는 모든 장치들을 파일로 관리
합니다. 따라서, 파일을 어떻게 관리하는지 알면 장치들을 손쉽게 제어할 수 있습니다.
사용할 syscall API에 커서를 두고 Shift + K
를 입력합니다. 그러면 해당 API의 메뉴얼을 확인할 수 있습니다.
예를 들어, open()이라는 시스콜 API의 메뉴얼을 확인하면 다음과 같고, 더 많은 정보를 하단에서 찾아볼수 있습니다.
해당 메뉴얼에서 파라미터 값이나 특정 값들을 더 찾아보고 싶을 때에는 /[찾고자 하는 값]
을 통해 검색을 하고 n(다음) N(이전)
을 통해 추가로 검색합니다.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
// use syscall : open, read, close
// fd : File Desciptor(정수형) => 하나의 프로그램이 파일에 접근하려고 할때, 부여되는 정수(번호)
int fd = open("./test.txt", O_RDONLY, 0); // 만약 fd가 음수면 error이다.
// ERROR 처리에 대한 로그메세지를 꼭 남기자
if(fd < 0)
{
printf("FILE OPEN ERROR\n");
exit(1); // 오류에 인한 종료
}
char buf[1000] = {0};
read(fd,buf,1000-1); // consider a null char
printf("%s",buf); // high level API
close(fd);
return 0;
}
open()의 메뉴얼
양식 : int open(path, flag, mode)
flag
필수옵션
추가옵션 : 필수옵션 | 추가옵션 이렇게 사용한다. ex) O_RDONLY|O_CREAT
mode
0777 : rwxrwxrwx
0644 : rw-r--r-- (보통 이거 씀)
#include <stdio.h>
// 메뉴얼 확인 : open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// 메뉴얼 확인 : write(), close()
#include <unistd.h>
// 메뉴얼 확인 : exit()
#include <stdlib.h>
// 메뉴얼 확인 : strlen()
#include <string.h>
int main()
{
int fd = open("./test.txt",O_WRONLY|O_TRUNC, 0664);
if(fd <0) // 에러 로그 메세지
{
printf("OPEN FILE ERROR\n");
exit(1);
}
char *buf = "HI SYSTEM CALL";
write(fd, buf, strlen(buf)); // 해당 문자열을 파일에 적기
printf("%s\n",buf);
close(fd);
return 0;
}
READ & WRITE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int fd = open("./cal.txt", O_RDONLY, 0644); // 읽기전용
char buf[1000] = { 0 };
read(fd, buf, 1000); // 1값 읽기
close(fd);
int num = atoi(buf); // 불러온 문자 숫자로 바꾸기
num *= 2; // 2씩 곱하기
printf("\n===[%d]===\n", num);
sprintf(buf, "%d", num);
fd = open("./cal.txt", O_WRONLY | O_TRUNC, 0644); // 기존에 적힌 문자 지우고 새로 쓰기
write(fd, buf, strlen(buf));
close(fd);
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct Node // 구조체 정의
{
int x,y,z;
}go;
int main()
{
int fd = open("./test.txt", O_WRONLY|O_TRUNC,0644); // 쓰기 전용으로 열기
if(fd < 0)
{
printf("ERROR OPEN FILE\n");
exit(1);
}
go temp = {3,5,99}; // 구조체 초기화
write(fd, &temp, sizeof(temp)); // 시작 주소와 길이 입력
close(fd);
return 0;
}
test.txt
: binary 값으로 들어간다.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct Node // 구조체 정의
{
int x,y,z;
}go;
int main()
{
int fd = open("./test.txt", O_RDONLY, 0664);
if(fd < 0)
{
printf("ERROR OPEN FILE");
exit(1);
}
go temp; // 구조체 선언
read(fd,&temp,sizeof(temp)); // 구조체 읽기
printf("%d %d %d\n", temp.x, temp.y, temp.z); // 구조체 나누어 출력 : 3 5 99
close(fd);
return 0;
}
offset
: 저장장치가 어디까지 읽었는지
내부적으로 동작한다. raed를 수행하면 offset값이 그 다음으로 이동한다.
lseek
: 기준점에서 offset만큼 떨어져 있는 곳으로 offset을 옮기는 시스템 콜
lseek(fd, 기준으로 이동할 값, 기준)
: 값은 음수도 가능하다.
기준
:
1. SEEK_CUR : 현재위치에서 부터
2. SEEK_SET : 시작점에서 부터
3. SEEK_END : 끝 지점에서 부터
다음 코드를 통해 완벽히 lseek와 offset을 이해해보자.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("./test.txt", O_RDONLY, 0); // 37byte의 값이 test.txt에 들어있다.
if(fd < 0)
{
printf("ERROR FILE OPEN\n");
exit(1);
}
char buf[11] = {0};
int n;
n = lseek(fd, 0, SEEK_CUR); // 현재 위치는 아무것도 읽지 않았으므로 0인 상태
printf("%d\n",n); // 0
read(fd,buf,10); // 10만큼 읽고 offset도 +10 이 된다. => 현재 offset : 10
n = lseek(fd, 0, SEEK_CUR); // 현재 위치 OFFSET을 변수에 넣기
printf("%d\n",n); // 10
n = lseek(fd, 5, SEEK_CUR); // 현재 위치에서 +5한 OFFSET 넣기
printf("%d\n",n); // 15
n = lseek(fd, -6, SEEK_CUR); // 현재 위치에서 -6한 OFFSET 넣기
printf("%d\n",n); // 9
n = lseek(fd, 0, SEEK_SET); // 맨 처음 위치 OFFSET 넣기
printf("%d\n",n); // 0
n = lseek(fd, 0, SEEK_END); // 맨 끝 위치 OFFSET 넣기
printf("%d\n",n); // 37
n = lseek(fd, 10, SEEK_SET); // 맨 앞 위치에서 +10한 OFFSET 넣기
printf("%d\n",n); // 10
close(fd);
return 0;
}