시스템 콜에 대해 공부중입니다. syscall_64.c에서의 함수 선언

‍남상진[ 학부재학 / 컴퓨터학과 ]@Google의 이미지

안녕하세요. syscall_64.c에서, 함수 선언 시 인자들이 전부 unsigned long 6개로 통일되어 선언되는 것으로 보입니다. 하지만 시스템 콜마다 인수 형태나 개수가 전부 다 다른데 어떻게 오류 없이 컴파일이 되는지, 어떤 처리에 의해 모든 시스템 콜의 정의가 인수 6개로 바뀌어서 가능한 것인지 여쭤보고자 합니다. 열심히 구글링 해보았으나 찾을 수가 없어 여기에 글을 올리게 되었습니다.
읽어주셔서 감사드립니다.

익명 사용자의 이미지

각각의 함수마다 인자가 다르거나, 즉, 각각의 함수 프로토타입이 다르거나,
매크로를 사용했겠죠. 함수가 동일 이름을 가졌다고 가정하면, va_arg 로 받으면 되겠죠.
printf () 문을 보면 함수 이름은 동일한데, 인자가 1개일 수도, 2개일 수도, 3개일 수도...있습니다.
그래도 컴파일하면 에러가 안 납니다. c언어에서 그런게 가능합니다.

‍남상진[ 학부재학 / 컴퓨터학과 ]@Google의 이미지

5.0에서
제가 정의한 시스템 콜 형태가
asmlinkage long __x64_sys_mycall(void) {
printk(KERN_ALERT "Hi₩n");
} 입니다.

그런데, syscall_64.c에 의하면 함수 참조를 위한 선언 내용이
extern asmlinkage long __x64_sys_mycall(struct pt_regs *);
이고, 이것을 시스템 콜 테이블에 등록까지 하는 걸 볼 수 있었습니다. 커널 컴파일 후 시스템 콜 또한 정상 작동되는 것을 확인할 수 있었구요
위에서 보면, SYSCALL_MACRO같은 매크로를 안 쓰고 단순히 저렇게 정의했는데, 함수명은 그대로이지만 인자 형태가 바뀐 것을 가지고 어떻게 참조해오는 것인지 알고 싶습니다. 아직 C에 대해 모르는 것이 많아 핑프같고 실례될 수도 있지만 너무 궁금해서 여쭤봅니다..

익명 사용자의 이미지

https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscall_64.c 여기보면
__x64_sys_mycall 함수는 보이지 않네요

익명 사용자의 이미지

헤더 파일보면
https://www.stolaf.edu/people/rab/os/lab/pub/cs273/arch+x86+include+generated+asm+syscalls_64.h
이런 식으로 되어 있고, 매크로로 작성된 함수를 보면 아래처럼 struct pt_regs * 가 있습니다.
https://lwn.net/Articles/752422/
.h 파일에서 함수 프로토타입을 선언하고 거기에 맞춰서 함수 내용을 작성하는 방식은 아닌거죠.
#define 문입니다.

익명 사용자의 이미지

asmlinkage long __x64_sys_mycall(void)은 제가 linux/kernel 내부에 임의로 정의한 시스템 콜입니다. 원래는 없는 거구요. 또 컨벤션하게 원래 써야하는 SYSCALL_DEFINE 매크로는 사용하지 않고, 제가 명확하게 저 형태로 적어서 정의했습니다.
syscall_64.tbl에는
335 mycall __x64_sys_mycall 이 형태로 한 줄 추가해주었고, 따라서
make시 생성되는 syscall_64.h 마지막 부분에
#ifdef CONFIG_X86
__SYSCALL_64(335, __x64_sys_mycall, )
#else
__SYSCALL_64(335, sys_mycall, ) 이러한 형태가 추가됩니다.

SYSCALL_DEFINEx (0이 아닌, 1~6)의 경우는 이해가 갑니다. wrapping을 하고 있는 것이 보입니다. 하지만, 0의 경우는, syscall_wrapper.h를 보면 단순히 asmlinkage long __x64_sys_함수명(void)로만 wrapping하고 이후의 처리가 없습니다. 이거는 논외로 하고, 제 문제는 이러한 매크로 없이, asmlinkage long __x64_sys_mycall(void)만을 정의했었습니다. 그런데, syscall_64.c에서, include되는 syscall_64.h 내부의 매크로들을 주르르륵 변환하면 extern asmlinkage long __x64_sys_mycall(struct pt_regs *)가 표현이 되고, 또 sys_call_table = { ..., [335] = __x64_sys_mycall }이 되는데, 저는 저 형태의 함수를 정의한 적이 없는데 어떻게 가져오는지가 궁금합니다.

익명 사용자의 이미지

리눅스 커널 소스를 보지는 않았는데, 스크립트(스캐너)가 소스코드를 생성해주는 경우도 있습니다.
개발자가 정의하지 않은 함수가 자동 생성되어서 컴파일되는 경우도 있죠.
아마 리눅스 커널 소스도 자동화하는 코드가 있을 것으로 보입니다.

그리고 c언어로 만들어진 glib를 보면
https://developer.gnome.org/gobject/stable/glib-mkenums.html
c 코드를 자동으로 생성해줍니다.

흔한 예로, .po 파일을 작성 후, make 명령하면 autotools 가 .po 파일을 스캔하여 여러 처리를 거쳐 .mo 를 만듭니다.

또 흔한 예로, jekyll 을 들 수 있는데, .md 파일을 사람이 작성하면 jekyll 이 그걸 처리하여 html 로 변환해 줍니다. 사람이 직접 html 을 작성하지 않아도요.

c언어 소스코드도 자동화가 가능한 부분이 있습니다.
c언어 자체에서 지원하지는 않고, 자동화하는 코드를 사람이 동적언어 또는 c언어로 그런 툴을 만들어야겠죠.

익명 사용자의 이미지

예를 들게요, 모듈(플러그인) 인터페이스를 정해놓읍시다.

Module *module_new (void);
bool module_start (Module *module);
bool module_stop (Module *module);
void module_free (Module *module);

모듈(플러그인) 이름을 sample 라고 합시다.
그러면 sample 이라는 이름을 개발자가 module.list 에 넣으면,
make 할 때 module.list 파일을 읽어서
sample_module.c 파일을 자동으로 생성해주는 스크립트를 못/안 만드는게 오히려 이상한거죠.
리눅스 커널 소스가 이상하다는 얘기가 아닙니다. 초능력을 써서 그러한 일이 발생된다는 것이 아니라는거죠.

Module *module_new ()
{
  ...
  return module;
}
 
void module_free (Module *module)
{
  ...
}

main.c 에서는 dlopen 으로 module_sample.so 파일을 읽어서
module_new, module_start, module_stop, module_free 심볼을 실행시키면 됩니다.

module_hello.so 라는 모듈을 만들었다고 칩시다.
main.c 에서 dlopen 으로 module_hello.so 파일을 읽어서
마찬가지로 동일한 인터페이스로
module_new, module_start, module_stop, module_free 심볼을 실행시키면 됩니다.

그러면 어떻게 분간을 해주냐?

int   module_get_id   (Module *module);
char *module_get_name (Module *module);

참 쉽죠잉?
boilerplate code 를 자동으로 생성하는게 가능합니다.
리눅스 커널 소스도 그런 방법을 사용하나보죠.
익명 사용자의 이미지

제가 질문을 제대로 이해했는지 모르겠네요.
보일러플레이트 코드 자동 생성에 관한 질문이 아니었다면,
c 프리프로세서에 대해 알아보시면 되겠습니다.
위 말씀하신 것들은 초능력을 쓴다던가... 그런건 아니고,

c 프리프로세서, 보일러플레이트 코드 자동 생성, 함수 포인터, dlopen

에 대해 아시면 의문이 생기지 않는 것들입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.