일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- hardware
- 포트 번호 변경
- Machine Learning
- kernel
- Operating System
- software
- Cache
- FTL
- storage system
- memory
- core dumped
- framework
- performance
- overflow
- rocksdb
- Flash Memory
- deep learning
- 시스템 프로그래밍
- Git
- 시스템 소프트웨어
- Samsung
- linux
- 키워드
- ssd
- github
- USENIX
- 커널 프로그래밍
- Intel
- Today
- Total
Happy to visit my research note ^^
linux에서 buffer에 timestamp를 찍기를 원할 때 알면 좋은 것들 본문
linux에서 buffer에 timestamp를 찍기를 원할 때 알면 좋은 것들
Liam Lim 2023. 2. 22. 17:04
" stdarg.h 헤더파일에 있는 기능들 "
stdarg.h 헤더파일에는 va_list, va_start(), va_end()가 정의되어있는데
해당 함수와 구조체는 stdarg.h 해더 파일에서 정의되는 @가변 인자 함수를 사용하기 위한 메크로와 타입이다.
@ 가변 인자 함수란 매개 변수의 개수가 정해져 있지 않고 호출될 때마다 다른 개수의 인자를 받을 수 있는 함수를 의미한다.
가변 인자 함수는 va_start, va_arg, va_copy, va_end와 같은 매크로를 사용하여 가변 인자를 처리한다. va_start 매크로는 가변 인자 목록에서 첫 번째 가변 인자를 가리키는 포인터를 초기화하고, va_arg 매크로는 다음 가변 인자를 가져온다.
예를 들어 printf 함수는 가변 인자 함수의 대표적인 예로 문자열과 함께 인자 목록을 받아서 형식화된 문자열을 출력한다. printf 함수에서는 첫 번째 인자로 출력할 형식화된 문자열을 받고, 그 다음 인자로는 해당 형식에 맞는 값들을 받는다. 이때, printf 함수는 인자의 개수가 정해져 있지 않기 때문에 가변 인자 함수로 구현된다.
가변 인자 함수를 사용하는 경우, va_list 타입의 변수를 선언하여 인자 목록을 처리할 수 있다. va_start 매크로를 이용하여 가변 인자 처리를 시작하고, va_arg 매크로를 이용하여 가변 인자 목록에서 인자를 읽어올 수 있다. va_end 매크로는 가변 인자 처리를 종료한다.
커널 프로그래밍에서는 가변 인자 함수가 종종 사용되며, 예를 들어 printk 함수가 가변 인자 함수이다. 따라서 printk 함수와 같은 커널 함수를 사용할 때 va_list, va_start를 사용하여 가변 인자를 처리할 수 있다.
+ 참고
' vsnprintf() ' 함수는 문자열을 포맷팅하는 함수 중 하나로, 가변 인자를 처리하는 함수인 ' vprintf ' 와 유사하게 동작하지만 출력 대상이 파일이나 터미널이 아닌 버퍼에 쓰여진다는 점에서 차이가 있다.
' vsnprintf() ' 함수의 호출 방법은 ' snprintf() ' 함수와 유사하지만, 가변 인자를 처리하는 방법이 조금 다르다. ' vsnprintf() ' 함수는 ' va_list ' 타입의 가변 인자 리스트를 받으며, 이를 처리하기 위해 ' stdarg.h ' 헤더파일을 반드시 포함해야 한다.
' vsnprintf() ' 함수는 다음과 같은 형태로 선언된다.
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
- str : 출력할 문자열을 저장할 버퍼의 포인터
- size : 버퍼의 크기
- format : 출력할 문자열의 형식
- ap : 가변 인자 리스트를 저장한 va_list 타입의 변수
' vsnprintf() ' 함수는 버퍼에 저장된 문자열의 길이를 int 자료형으로 반환한다. 버퍼의 크기가 충분하지 않아 문자열이 잘리는 경우 버퍼 크기와 관계없이 문자열이 잘리고, 반환값은 원래 출력하려던 문자열의 길이가 된다.
+ 참고
추가로 stdarg.h에 정의되어 있는 vsprintf 와 vsnprintf 함수는 서식 문자열과 가변 인자들을 사용하여 문자열을 생성하는 함수이다.
vsprintf 함수는 생성된 문자열을 문자 배열에 저장한다. 이 함수는 출력 문자열의 크기를 알 수 없으므로 @버퍼 오버플로우 등의 위험이 있다.
반면, vsnprintf 함수는 출력 문자열의 최대 길이를 제한하여 문자열을 생성하므로, 버퍼 오버플로우를 방지할 수 있다. 생성된 문자열은 문자 배열에 저장된다.
따라서, vsnprintf가 더 안전하여 문자열을 생성할 수 있다.
@ 버퍼 오버플로우 (Buffer Overflow)는 데이터를 저장하는 버퍼가 일정 크기를 넘어서는 데이터를 담지 못하고 데이터가 초과될 때 발생하는 보안 취약점 중 하나이다. 보통 프로그램에서 배열 형태의 버퍼에 데이터를 복사할 때, 버퍼의 크기를 검사하지 않거나 검사를 제대로 하지 않을 경우 발생한다.
' vsprintf ' 함수는 ' sprintf ' 함수와 유사하게 서실 문자열을 이용하여 문자열을 생성하는 함수이다. 다만, ' sprintf ' 는 출력할 문자열의 길이를 검사하지 않기 때문에 버퍼 오버플로우 취약점이 있다. 따라서, ' vsprintf ' 를 사용하면 출력할 문자열의 길이를 미리 지정할 수 있기 때문에 버퍼 오버플로우 취약점을 보안할 수 있다.
예를 들어, char buf[10] 이라는 10 바이트 크기의 버퍼를 가지고, ' vsprintf ' 함수를 이용해 "Hello World!" 라는 문자열을 저장하려고 하면, ' buf '에 "Hello Wor"까지만 저장되고, 나머지 "ld!"는 저장되지 않는다. 이렇게 버퍼의 크기를 초과하여데이터가 저장될 경우, 프로그램의 비정상적인 종료나 기타 보안 취약점으로 이어질 수 있다.
조금 위의 글에서 vsnprintf()와 vsprintf()의 차이는 vsnprintf는 버퍼 오버플로우를 방지할 수 있고 vsprintf 는 sprintf에 비교해 버퍼 오버플로우를 보안할 수 있다.
" 가변 인자 함수 printf "
printf( ) 함수는 표준 라이브러리인 stdio.h 헤더 파일에 선언되어 있는 함수로, 서식 지정자를 사용하여 택스트를 출력하는 함수이다.
#include <stdio.h>
int printf(const char* format, ...) {
va_list args;
va_start(args, format);
int written = vfprintf(stdout, format, args);
va_end(args);
return written;
}
위 코드는 printf() 함수의 간단한 예시이다.
실제 printf() 함수의 코드는 C 표준 라이브러리에서 제공되는 함수이다. 위 코드에서는 va_list, va_start, vfprintf, va_end 함수를 사용한다.
printf() 함수는 가변 인자 함수입니다. 가변 인자 함수를 구현할 때는 가변 인자 목록을 처리하기 위해 <stdarg.h> 헤더 파일을 include하고, va_list, va_start, va_arg, va_end 함수를 사용한다. va_list 타입은 가변 인자 목록을 포함하는 타입이고, va_start 함수를 사용하여 가변 인자 목록을 초기화한다. va_arg 함수를 사용하여 가변 인자 목록에서 값을 가져올 수 있으며, va_end 함수를 사용하여 가변 인자 목록을 정리한다.
printf() 함수의 내부에서는 va_start 함수를 사용하여 가변 인자 목록을 초기화하고, vfprintf 함수를 사용하여 포맷 문자열과 가변 인자 목록을 기반으로 문자열을 포맷팅하여 stdout에 출력한다. vfprintf() 함수는 파일 스트림에 포맷팅된 문자열을 출력하는 함수이며, printf() 함수에서는 stdout을 출력 대상으로 설정한다.
위 코드에서는 vfprintf 함수의 반환값을 저장해서 출력된 문자열의 길이를 반환한다. va_end 함수로 가변 인자 목록을 정리한 뒤, 출력된 문자여의 길이를 반환한다.
printf() 함수는 출력한 문자열의 길이를 반환한다. 출력에 실패하면 음수를 반환한다.
'Kernel & Linux programming with C Lang' 카테고리의 다른 글
Kernel linux 개발에 도움되는 라이브러리 정리 (0) | 2023.02.28 |
---|---|
내가 쓰는 파일 입출력에 대한 간단한 정리 (0) | 2023.02.28 |
kernel에서 함수 정의 시 static 키워드를 자주 사용하는 이유 (0) | 2023.02.22 |
kernel 개발에 필요한 키워드 정리 (c lang) (0) | 2023.02.22 |
상/하위 레이어 함수 간의 코드를 공유하는 방법 (0) | 2023.02.22 |