임베디드 실습 #1 기초 실습 Hanbat National University Prof. Lee Jaeheung
차례 리눅스 사용 방법 C언어 기초 실습 스레드 소켓 통신 기본 명령어 VI 에디터 GCC 컴파일 서버, 클라이언트 동적 메모리 사용 파일 처리 스레드 소켓 통신 서버, 클라이언트 Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 기본 명령어 $ pwd : 현재 경로확인 $ cd [경로] : 해당 경로로 이동 $ ls : 현재 디렉토리의 파일 확인 $ mkdir [디렉토리명] : 디렉토리 생성 $ rmdir [디렉토리명] : 디렉토리 삭제 $ rm –r [디렉토리명] : 디렉토리 삭제 $ rm [파일명] : 파일 삭제 $ cp [파일명1] [파일명2] : [파일명1]을 [파일명2]로 복사 $ mv [파일명1] [파일명2] : [파일명1]을 [파일명2]로 이동 Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 VI 필수 단축키 저장 – ESC -> : -> w 저장 후 종료 - ESC -> : -> wq 또는 wq! 저장 않고 종료 – ESC -> : -> q 또는 q! 입력모드 – i 줄삽입 – o 줄복사 – y 붙여넣기 – p 맨 윗줄로 커서 이동 – gg 맨 마지막줄로 커서 이동 – G (shift + g) Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 VI 실습 # vi test.c #include <stdio.h> int main() { int i, j; int n = 5; for( i=0 ; i<n ; i++ ) for( j=0; j<=i ; j++ ) printf("*"); } printf("\n"); return 0; Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 VI 설정 $ vi ~/.vimrc set cindent set number Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 GCC 컴파일러 GCC 컴파일러란? GCC 버전 확인 방법 GCC(GNU Compiler Collection)는 GNU 프로젝트의 일환으로 개발되어 널리 쓰이고 있는 컴파일러 C/C++, JAVA, 포트란, 에이다등 여러 언어를 컴파일 가능 GCC 가장 최근버전은 7.3 GCC 버전 확인 방법 gcc -v [test:~]$ gcc -v Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu Thread model: posix gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12) Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 GCC 컴파일러 컴파일 방법 gcc -o [생성할목적파일이름] [컴파일할소스파일이름] ex) gcc -o test test.c 오류가 없는 경우 오류가 있는 경우 [test:~/test]$ gcc -o test test.c [test:~/test]$ [test:~/test]$ gcc -o test test.c test.c: In function ‘main’: test.c:9: error: expected ‘,’ or ‘;’ before ‘for’ test.c:9: error: expected ‘;’ before ‘)’ token test.c:9: error: expected statement before ‘)’ token [test:~/test]$ Hanbat National University Prof. Lee Jaeheung
리눅스 사용 방법 GCC 컴파일러 실행 방법 $ ./[파일명] 입력 후 엔터 실행 파일에 실행 권한이 없는 경우 대한 권한 변경 chmod +x [파일명] Ex) 실행 권한이 없는 파일을 실행 했을 경우 [test:~/test]$ gcc -o test test.c [test:~/test]$ chmod +x test [test:~/test]$ ./test * ** *** **** ***** [test:~/test]$ [test:~/test]$ ./test -bash: ./test: Permission denied Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 동적 메모리 사용 함수 종류 메모리 할당 메모리 해제 100Bytes 메모리 할당 예제 malloc : 속도 빠름, 자동 초기화 시키지 않음 calloc : malloc과 동일, 0으로 자동 초기화 시킴 realloc : 이미 할당된 메모리 사이즈를 변경해야 하는 경우 사용 메모리 해제 free : 할당 한 메모리를 해제함 100Bytes 메모리 할당 예제 #include <stdlib.h> char *array = (char *)malloc(100); memset(array, 0, 100); free(array); Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 파일 처리 방법 FILE 구조체 사용 FD(File Descriptor) 사용 리눅스/윈드우즈 계열에서 모두 사용 가능 고수준 입출력 처리 FD(File Descriptor) 사용 리눅스 계열에서만 사용 가능 파일을 관리하기 위해 운영체제가 필요로하는 파일의 정보를 가짐 파일의 지칭을 하기 위해 부여된 숫자 저수준 입출력 처리 파일뿐만 아니라 디바이스 장치, 소켓등 공통적으로 사용 Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 FD 지원 함수 열기 open : 파일 오픈 함수 Ex) 읽기 전용 파일 열기 파일 모드 종류 [ int open(const char *filename, int mode) ] Ex) 읽기 전용 파일 열기 파일 모드 종류 O_RDONLY : 읽기전용으로 오픈 O_WRONLY : 쓰기전용으로 오픈 O_RDWR : 읽기/쓰기 모드로 오픈 O_APPEND : 파일 오픈 후 파일 포인터를 가장 끝으로 이동 O_CREAT : 파일이 존재하지 않으면 생성하여 오픈 O_TRUNC : 파일이 존재하면 내용을 모두 지운 후 오픈 #include <fcntl.h> int fd = open(“test.txt”, O_RDONLY); Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 FD 지원 함수 열기 파일 모드 조합 // 읽기, 쓰기가 가능하고 덧붙이기 모드로 오픈 int fd = open(“test.txt”, O_RDWR | O_APPEND); // 읽기, 쓰기가 가능하고 파일이 존재하지 않으면 생성 후 오픈 int fd = open(“test.txt”, O_RDWR | O_CREAT); // 읽기, 쓰기가 가능하고 파일이 존재하면 모두 삭제, 존재하지 않으면 생성 int fd = open(“test.txt”, O_RDWR | O_CREAT | O_TRUNC); Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 FD 지원 함수 읽기 read : FD로부터 원하는 만큼의 데이터를 얻어옴 [ int read(int fd, void *buffer, int length) ] Ex) 파일 오픈 후 100Byte를 읽어옴 #include <unistd.h> int fd, len; char buffer[100]; fd = open(“test.txt”, O_RDONLY); len = read(fd, buffer, 100); Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 FD 지원 함수 쓰기 write : FD로 원하는 만큼의 데이터를 내보냄 [ int write(int fd, void *buffer, int length) ] Ex) 파일 오픈 후 문자열을 덧붙임 #include <unistd.h> int fd, len; char buffer[100]; fd = open(“test.txt”, O_RDWR | O_APPEND); sprintf(buffer, “TEST APPEND\n”); len = write(fd, buffer, strlen(buffer)); Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 FD 지원 함수 닫기 close : FD를 닫음 Ex) 파일 오픈 후 FD를 닫음 [ int close(int fd) ] Ex) 파일 오픈 후 FD를 닫음 #include <unistd.h> int fd; fd = open(“test.txt”, O_RDWR); close(fd); Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 파일 크기 구하기 stat 파일의 정보를 구조체에 저장하여 넘겨줌 [ int stat(const char *path, struct stat *buf) ] struct stat 구조 struct stat { dev_t st_dev; /* 디바이스 정보 */ ino_t st_ino; /* 아이노드 정보 */ mode_t st_mode; /* 파일 타입 */ nlink_t st_nlink; /* 링크된 갯수 */ uid_t st_uid; /* 소유주 식별번호 */ gid_t st_gid; /* 소유그룹 식별번호 */ off_t st_size; /* 파일 크기(Bytes) */ time_t st_atime; /* 마지막 접근시간 */ time_t st_mtime; /* 마지막 수정 시간 */ time_t st_ctime; /* 마지막 갱신 시간 */ ...(중략) }; Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 파일 처리 파일 크기 구하기 stat Ex) 파일크기 구하기 #include <sys/stat.h> int filesize; struct stat stat_buf; stat(“test.txt”, &stat_buf); filesize = stat_buf.st_size; printf(“FileSize = %d\n”, filesize); Hanbat National University Prof. Lee Jaeheung
1. “test.txt” 파일 생성, hello 작성 후 저장 C언어 기초 실습 실습 텍스트 파일의 데이터를 화면에 출력하는 프로그램(동적메모리사용) 1. “test.txt” 파일 생성, hello 작성 후 저장 2. 파일 사이즈 구하기 3. 파일 사이즈만큼 메모리 동적할당 4. 파일 오픈 5. 파일 읽기 6. 파일 내용 화면 출력 Hanbat National University Prof. Lee Jaeheung
C언어 기초 실습 실습 Hanbat National University Prof. Lee Jaeheung #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <stdlib.h> #include <unistd.h> int main() { int fd, len; int filesize; struct stat stat_buf; char *buffer; stat("test.txt", &stat_buf); // 파일 정보 읽기 filesize = stat_buf.st_size; // 파일 사이즈 구하기 buffer = (char *)malloc(filesize* sizeof(char)); // 메모리 동적할당 fd = open("test.txt", O_RDONLY); // 파일 읽기 len = read(fd, buffer, filesize); // 버퍼에 파일 내용 가져오기 printf("%s", buffer); // 버퍼 출력 close(fd); // 파일 닫기 return 0; } Hanbat National University Prof. Lee Jaeheung
스레드 개요 정의 장점 단점 프로세스 내의 독립적인 순차 흐름 또는 제어 경량 프로세스(Light-Weight Process) 하나의 프로세스 내에서 둘 이상의 흐름을 만들 때 사용 장점 프로세스 보다 컨텍스트 스위칭이 빠름 프로세스 보다 적은 리소스를 사용하여 생성 가능 스레드는 다른 스레드와 메모리 공유가 가능 단점 공유 메모리에 동시 접근 문제(임계영역) 공유 메모리에 대한 뮤텍스 또는 세마포어 필요 Hanbat National University Prof. Lee Jaeheung
스레드 함수 int pthread_create( // pthread 생성 pthread_t *thread, // thread ID를 저장할 변수 const pthread_attr_t *attr, // thread 속성(옵션) void *func (void *arg), // thread 생성 후 실행될 함수 void *arg); // func 함수에 전달하는 인자 int pthread_join( // thread 종료를 대기 pthread_t th, // 대기할 thread void **retval); // 종료시 반환 값 Hanbat National University Prof. Lee Jaeheung
스레드 사용법 Hanbat National University Prof. Lee Jaeheung #include <stdio.h> #include <pthread.h> #include <unistd.h> void *print_thread(void *arg); int main(){ pthread_t th_1; int id_1 = 0; id_1 = 1; pthread_create(&th_1, NULL, print_thread, &id_1); getchar(); id_1 = 0; pthread_join(th_1, NULL); return 0; } void *print_thread(void *arg){ int *id = (int *)arg; while( *id > 0 ){ printf("Thread ID = %d\n", *id); usleep( 1000 * 1000 ); return NULL; # gcc –o thread_test thread_test.c –lpthread Hanbat National University Prof. Lee Jaeheung
스레드 실습 : 스레드 테스트 하나의 프로세스에서 3개의 print_thread를 생성 3개의 스레드는 각각 1, 2, 3 을 출력 Hanbat National University Prof. Lee Jaeheung
스레드 실습 : 스레드 테스트 Hanbat National University Prof. Lee Jaeheung #include <stdio.h> #include <pthread.h> #include <unistd.h> void *print_thread(void *arg); int main(){ pthread_t th_1, th_2, th_3; int id_1, id_2, id_3; id_1 = 1; id_2 = 2; id_3 = 3; pthread_create(&th_1, NULL, print_thread, &id_1); pthread_create(&th_2, NULL, print_thread, &id_2); pthread_create(&th_3, NULL, print_thread, &id_3); getchar(); id_1 = id_2 = id_3 = 0; pthread_join(th_1, NULL); pthread_join(th_2, NULL); pthread_join(th_3, NULL); return 0; } void *print_thread(void *arg){ int *id = (int *)arg; while( *id > 0 ){ printf("Thread ID = %d\n", *id); usleep( 1000 * 1000 ); return NULL; Hanbat National University Prof. Lee Jaeheung
소켓 통신 필요성 전송 방식 네트워크를 이용하여 원격지에 존재하는 호스트와 연결 연결 후 TCP 통신을 이용하여 데이터 전송 UDP 통신 : 비연결지향성(고속 전송) Hanbat National University Prof. Lee Jaeheung
소켓 통신 함수 int socket(int domain, int type, int protocol); int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int listen(int sockfd, int backlog); int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); int connect(int socket, const struct sockaddr *address, socklen_t address_len); Hanbat National University Prof. Lee Jaeheung
소켓 통신 서버 클라이언트 1. 소켓 생성 ( socket 함수 호출) 2. IP주소 및 PORT번호 할당 (bind 함수 호출) 3. 연결요청 대기 (listen 함수 호출) 4. 연결요청 수락 (accept 함수 호출) 클라이언트 1. 소켓 생성 (socket 함수 호출) 2. 연결 요청 (connect 함수 호출) Hanbat National University Prof. Lee Jaeheung
소켓 통신 실습파일 - http://artoa.hanbat.ac.kr/lecture_data/embedded_sw/tcp/server.c - http://artoa.hanbat.ac.kr/lecture_data/embedded_sw/tcp/client.c Hanbat National University Prof. Lee Jaeheung
서버 모드 ( server.c ) - $ gcc –o server server.c - $ ./server 1234 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; char message[BUF_SIZE]; int str_len, i; struct sockaddr_in serv_adr; struct sockaddr_in clnt_adr; socklen_t clnt_adr_sz; if(argc!=2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } serv_sock=socket(PF_INET, SOCK_STREAM, 0); if(serv_sock==-1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); serv_adr.sin_port=htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("bind() error"); if(listen(serv_sock, 5)==-1) error_handling("listen() error"); clnt_adr_sz=sizeof(clnt_adr); clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); if(clnt_sock==-1) error_handling("accept() error"); else printf("Connected client %d \n", i+1); while(1){ str_len=read(clnt_sock, message, BUF_SIZE-1); message[str_len]=0; printf("Message from client: %s", message); write(clnt_sock, "I got your message", strlen("I got message")); } close(clnt_sock); close(serv_sock); return 0; void error_handling(char *message){ fputs(message, stderr); fputc('\n', stderr); exit(1); Hanbat National University Prof. Lee Jaeheung
- $ gcc –o client client.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int sock; char message[BUF_SIZE]; int str_len; struct sockaddr_in serv_adr; if(argc!=3) { printf("Usage : %s <IP> <port>\n", argv[0]); exit(1); } sock=socket(PF_INET, SOCK_STREAM, 0); if(sock==-1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=inet_addr(argv[1]); serv_adr.sin_port=htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("connect() error!"); else puts("Connected..........."); while(1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) break; write(sock, message, strlen(message)); str_len=read(sock, message, BUF_SIZE-1); message[str_len]=0; printf("Message from server: %s\n", message); } close(sock); return 0; void error_handling(char *message) fputs(message, stderr); fputc('\n', stderr); exit(1); Hanbat National University Prof. Lee Jaeheung