NetBSD 커널 모듈 샘플을 사용해보십시오
15570 단어 AdventCalendarNetBSD
오늘은 NetBSD 커널 모듈에 대해 이야기하려고합니다.
커널 모듈
커널 모듈에 대해서는
module(7)
의 설명을 보는 것이 빠르다. 커널 모듈은 시스템 관리자가 가동중인 시스템에 동적으로 추가 및 삭제할 수 있는 기능으로 개발자가 재부팅을 필요로 하지 않는 형태로 커널 기능을 추가할 수 있습니다.DESCRIPTION
Kernel modules allow the system administrator to dynamically add and
remove functionality from a running system. This also helps software
developers add new parts of the kernel without constantly rebooting to
test their changes.
커널 모듈 샘플
NetBSD 소스 트리
sys/modules/examples
아래에는 커널 모듈 샘플이 있습니다.이번에는 이 샘플을 바탕으로 커널 모듈을 사용해 봅시다.
# cd /usr/src/sys/modules/examples
# ls -F
CVS/ Makefile.inc hello/ luareadhappy/ properties/
Makefile README luahello/ ping/ readhappy/
커널 모듈을 빌드하는 환경 만들기
커널 모듈의 샘플 코드는 빌드 툴 체인이 생성한 경로에 gcc가 있다고 가정한 Makefile입니다.
따라서 커널 모듈을 빌드하려면
build.sh
에서 셀프 호스트 용 툴 체인을 구축하는 것이 빠른 방법입니다.(전제적으로
/usr/src
에 커널 소스가 배포되었다고 가정합니다.)다음 단계를 통해 x86_64용 툴체인을 빌드합니다.
$ sudo bash
# cd /usr/src
# ./build.sh -m amd64 -a x86_64 -T /usr/src/tooldir.NetBSD-8.0-amd64 -r -o -U tools
모듈 샘플을 만져보세요
즉시 커널 모듈의 샘플을 만져보십시오.
샘플에는
hello
와 readhappy
라는 작은 2 개의 모듈이 준비되어 있으므로, 각각을 보자.hello 모듈
먼저
hello
모듈입니다. 코멘트를 제외하면 30행 정도의 소스 코드입니다.# cd hello
# ls -F
CVS/ Makefile hello.c
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hello.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $");
#include <sys/param.h>
#include <sys/module.h>
/*
* Last parameter of MODULE macro is a list of names (as string; names are
* separated by commas) of dependencies. If module has no dependencies,
* then NULL should be passed.
*/
MODULE(MODULE_CLASS_MISC, hello, NULL);
static int
hello_modcmd(modcmd_t cmd, void *arg __unused)
{
switch (cmd) {
case MODULE_CMD_INIT:
printf("Example module loaded.\n");
break;
case MODULE_CMD_FINI:
printf("Example module unloaded.\n");
break;
case MODULE_CMD_STAT:
printf("Example module status queried.\n");
break;
default:
return ENOTTY;
}
return 0;
}
make
명령으로 직접 빌드할 수 있습니다.# make
# ls -F
CVS/ amd64@ hello.kmod hello.o machine@
Makefile hello.c hello.kmod.map i386@ x86@
커널 모듈 로드
커널 모듈은
modload
명령으로 로드됩니다.# cd /usr/src/sys/modules/examples/hello/
#
# # まだhelloモジュールはロードされていない
# modstat | grep hello | wc -l
0
#
# # modloadコマンドでロード。
# # 「./」で相対パス指定にしないとロードエラーになるので注意。
# modload ./hello.kmod
#
# # helloモジュールがロードされていることを確認する。
# modstat | egrep 'NAME|hello'
NAME CLASS SOURCE FLAG REFS SIZE REQUIRES
hello misc filesys - 0 77 -
소스 코드와 대조하는 형태로, 커널 모듈의 로드 언로드가 어떻게 행동하는지를 살펴봅니다.
static int
hello_modcmd(modcmd_t cmd, void *arg __unused)
{
switch (cmd) {
case MODULE_CMD_INIT:
printf("Example module loaded.\n");
break;
모듈을로드하면 ....
# modunload hello
해당 처리는
hello_modcmd()
함수의 MODULE_CMD_INIT
를 처리합니다.static int
hello_modcmd(modcmd_t cmd, void *arg __unused)
{
switch (cmd) {
...中略...
case MODULE_CMD_INIT:
printf("Example module loaded.\n");
break;
modunload
의 경우 같은 함수의 MODULE_CMD_FINI
가 처리됩니다. case MODULE_CMD_FINI:
printf("Example module unloaded.\n");
break;
readhappy 모듈
그런 다음
readhappy
모듈을 살펴 보겠습니다. 이쪽도 심플한 코드 같네요.# cd /usr/src/sys/modules/examples/readhappy
# ls -F
CVS/ Makefile readhappy.c
여기도
make
명령으로 빌드하고 modload
명령으로로드합니다.# modload ./readhappy.kmod
# modstat | egrep '^NAME|happy'
NAME CLASS SOURCE FLAG REFS SIZE REQUIRES
happy misc filesys - 0 377 -
readhappy.c
의 소스 코드 코멘트를 보면 이하의 기술이 있으므로, 그에 따라 mknod 명령을 실행합니다. * Create a device /dev/happy from which you can read sequential
* happy numbers.
*
* To use this device you need to do:
* mknod /dev/happy c 210 0
# mknod /dev/happy c 210 0
# ls -l /dev/happy
crw-r--r-- 1 root wheel 210, 0 Dec 3 18:58 /dev/happy
# file /dev/happy
/dev/happy: character special (210/0)
소스 코드를 보면
readhappy.c
의 struct cdevsw.d_read
에 read(2)
에 해당하는 함수가 연결됩니다. 그런 다음 연결 된 happy_read()
함수에 적절한 printf()
를 삽입하여 동작을 살펴 보겠습니다.static struct cdevsw happy_cdevsw = {
...中略...
.d_read = happy_read,
...中略...
happy_read(dev_t self __unused, struct uio *uio, int flags __unused)
{
...中略...
/* Send it to User-Space */
int e;
printf("-=> (^_^)/ %s", line); // 確認用に追加した行。
if ((e = uiomove(line, len, uio)))
return e;
사용자 랜드 측에서 간단한 샘플 코드를 준비하고
/dev/happy
에서 데이터를 읽어보십시오.#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char buf[BUFSIZ];
int fd, i;
fd = open("/dev/happy", O_RDONLY);
if (fd == -1) {
fprintf(stderr, "open() failed.\n");
exit(-1);
}
for (i = 0; i < argc; i++) {
read(fd, buf, BUFSIZ);
printf("%s", buf);
}
close(fd);
return 0;
}
데이터를
read()
할 때마다 printf()
에서 추가한 문장이 커널 메시지로서 출력되고 있는 것과 커널내의 값 (데이터)이 read()
로 유저 랜드측에서도 취득할 수 있는 것을 알 수 있습니다.요약
NetBSD 커널 모듈에 대해 제공된 샘플을 바탕으로 빌드 및 로드 방법을 소개했습니다.
특히
readhappy.c
는 단순하면서도, 유저 랜드에의 데이터의 건네주는 방법 등, 삼키기를 누른 샘플이 되어 있습니다.커널 모듈의 샘플에는, 그 밖에도 Lua로 기술된 커널 모듈도 포함되어 있으므로, 이쪽도 나중에 소개할 수 있으면 좋겠습니다.
Reference
이 문제에 관하여(NetBSD 커널 모듈 샘플을 사용해보십시오), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/furandon_pig/items/647c21cbe21eeb3aafc2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)