Skip to content

Instantly share code, notes, and snippets.

@kimhoki
Last active August 29, 2015 14:23
Show Gist options
  • Save kimhoki/4884895ca6069c2bc063 to your computer and use it in GitHub Desktop.
Save kimhoki/4884895ca6069c2bc063 to your computer and use it in GitHub Desktop.
static과 외부 변수

static과 외부 변수

일반적인 aaa.c파일 내에서 외부 참조가 어떻게 실행이 되는지 알아보자.

aaa.c

#include <stdio.h>
extern bbb();
int aaa()
{
    printf("aaa called\n");
    return 0;
}

int main()
{
    aaa();
    bbb();

}

bbb.c

#include <stdio.h>
int bbb()
{
	printf("bbb called\n");
	return 0;
}

다음과 같이 aaa파일을 컴파일 하면 해보자. ##root@linux-VirtualBox:#gcc aaa.c 아마도 아래와 같이 에러가 뜰 것이다.

화면 표시:

/tmp/cckyz0rW.o: In function `main':
aaa.c:(.text+0x29): undefined reference to `bbb'
collect2: error: ld returned 1 exit status

사실 bbb라는 함수는 사실 bbb.c에 있다.

이것을 컴파일 하려면 컴파일 할때

bbb.c를 추가해 주면 된다.

##root@linux-VirtualBox:#gcc aaa.c bbb.c ##root@linux-VirtualBox:#./a.out

화면 표시:

aaa called
bbb called

이렇게 extrn을 사용 하는 것을 외부 참조라고 한다.

이제 커널모듈에서 외부 참조를 알아 보자.

첨부 코드

  • nosymbol.c
  • symbol1.c
  • symbol2.c
  • Makefile

Makefile:

KERNELDIR =	/lib/modules/$(shell uname -r)/build
obj-m	:= nosymbol.o symbol1.o symbol2.o
KDIR	:=	/lib/modules/$(shell uname -r)/build
PWD	:=	$(shell pwd)
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
	rm	-rf *.ko
	rm	-rf *.mod.*
	rm	-rf .*.cmd
	rm	-rf *.o
	rm	-rf .tmp_versions

nosymbol.c:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
 
MODULE_LICENSE("GPL");
 
static int module_begin(void)
{
	printk("Hello nosymbol!\n");
	return 0;
}
 
static void module_end(void)
{
	printk("Good bye");
}
 
module_init(module_begin);
module_exit(module_end);

** symbol1.c :**

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");

char *test;
void symbol_test(void)
{
	printk("%s \n", test);
}

EXPORT_SYMBOL (symbol_test);

static int module_begin(void)
{
	printk("Hello symbol1!\n");
	test = "This is a test. \n";
	return 0;
}
static void module_end(void)
{
	printk("Good bye symbol1");
}

module_init(module_begin);
module_exit(module_end);

** symbol2.c: **

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");

extern void symbol_test(void);

static int module_begin(void)
{
	printk("Hello symbol2!\n");
	symbol_test();
	return 0;
}
static void module_end(void)
{
	printk("Good bye symbol2\n");
}

module_init(module_begin);
module_exit(module_end);

##코드 파일과 Makefile 파일을 작성 하시고 밑 내용대로 명령어를 실행 하시면 됩니다.

make을 하여 nosymbol.ko, symbol1.ko, symbol2.ko 준비한다.

일단 nosymbol.ko파일을 올려 보자. ##root@linux-VirtualBox:#insmod nosymbol.ko ##root@linux-VirtualBox:#dmesg

화면 표시:

...
...
...
[38.479039] audit: type=1400 audit(1434530634.417:75): apparmor="STATUS" operatio
n="profile_replace" name="/usr/sbin/cupsd" pid=2178 comm="apparmor_parser"
[38.479354] audit: type=1400 audit(1434530634.417:76): apparmor="STATUS" operatio
n="profile_replace" name="/usr/sbin/cupsd" pid=2178 comm="apparmor_parser"
[1369.122239] Hello nosymbol!			<== 동작 확인.

사실 위의 예제는 static으로 선언이 되어 있을때 실행이 되는 여부를 알아 보기 위한 것이다.

이제 본격 적으로 static과 외부 선언을 확인해 보자.

##root@linux-VirtualBox:#cat /proc/kallsyms | grep symbol[12] insmod를 하지 않았기 때문에 심볼테이블에 아무것도 올라 가지 않았다.

따라서 화면 안에 아무것도 표시가 안될 것이다.

이제 insmod를 해보자. ##root@linux-VirtualBox:#insmod symbol2.ko

화면 표시:

insmod: ERROR: could not insert module symbol2.ko: Unknown symbol in module

삽입 할수 없다고 나올 것이다.

우리가 코드를 작성을 할때 symbol1안에 **symbol_test(void)**를 EXPORT 했다.

따라서 symbol1.ko파일이 먼저 올라가 있지 않으면 symbol2.ko파일이 삽입이 안된다. ##root@linux-VirtualBox:#insmod symbol1.ko ##root@linux-VirtualBox:#dmesg

화면 표시:

[ 2162.062027] Hello symbol1!

##root@linux-VirtualBox:#cat /proc/kallsyms | grep symbol[12]

화면 표시:

ffffffffa0049020 t module_begin 		[symbol1]
ffffffffa0049050 t module_end   		[symbol1]
ffffffffa004a080 r __kstrtab_symbol_test        [symbol1]
ffffffffa004a040 r __kcrctab_symbol_test        [symbol1]
ffffffffa004b000 d __this_module        	[symbol1]
ffffffffa0049050 t cleanup_module       	[symbol1]
ffffffffa0049020 t init_module  		[symbol1]
ffffffffa0049000 T symbol_test  		[symbol1]  <== 확인
ffffffffa004b260 b test 			[symbol1]
ffffffffa004a030 r __ksymtab_symbol_test        [symbol1]

모듈이 정상적으로 동작이 되었는것도 확인을 하였고 심볼테이블에 올려 진것도 확인하였다. 이제 2번째 심볼을 올려 보자. ####root@linux-VirtualBox:#insmod symbol2.ko ####root@linux-VirtualBox:#dmesg

화면 표시:

[ 2562.354554] Hello symbol2!
[ 2562.354558] This is a test.

##root@linux-VirtualBox:#cat /proc/kallsyms | grep symbol[12]

화면 표시:

ffffffffa003d000 t module_begin 		[symbol2]  << 추가됨 
ffffffffa003d020 t module_end   		[symbol2]  <<
ffffffffa003f000 d __this_module        	[symbol2]  <<
ffffffffa003d020 t cleanup_module       	[symbol2]  <<
ffffffffa003d000 t init_module  		[symbol2]  << 추가됨
ffffffffa0049020 t module_begin 		[symbol1]
ffffffffa0049050 t module_end   		[symbol1]
ffffffffa004a080 r __kstrtab_symbol_test        [symbol1]
ffffffffa004a040 r __kcrctab_symbol_test        [symbol1]
ffffffffa004b000 d __this_module        	[symbol1]
ffffffffa0049050 t cleanup_module       	[symbol1]
ffffffffa0049020 t init_module  		[symbol1]
ffffffffa0049000 T symbol_test  		[symbol1]
ffffffffa004b260 b test 			[symbol1]
ffffffffa004a030 r __ksymtab_symbol_test        [symbol1]

모든 모듈이 정상적으로 동작이 되었는것도 확인을 하였고 symbol2.ko안에 내용들이 심볼테이블에 올려 진것도 확인하였다.

##root@linux-VirtualBox:#lsmod

화면 표시:

Module          Size  	Used by
symbol2         16384  	0
symbol1         16384  	1 symbol2  << 심볼2가 심볼1을 참조 하고 있다. 
nosymbol        16384   0

모듈 symbol1을 다른 모듈1개가 사용 하고 있다. 따라서 symbol1를 참조 하고 있는 모든 모듈을 제거 하지 않으면 symbol1은 제거 되지 않는다. 제거 순서 symbol2 -> symbol1 -> nosymbol

##root@linux-VirtualBox:#rmmod symbol2 ##root@linux-VirtualBox:#dmesg ##root@linux-VirtualBox:#cat /proc/kallsyms | grep symbol[12] ##root@linux-VirtualBox:#lsmod ##root@linux-VirtualBox:#rmmod symbol1 ##root@linux-VirtualBox:#dmesg ##root@linux-VirtualBox:#cat /proc/kallsyms | grep symbol[12] ##root@linux-VirtualBox:#lsmod ##root@linux-VirtualBox:#rmmod nosymbol ##root@linux-VirtualBox:#dmesg ##root@linux-VirtualBox:#lsmod

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment