2022-06-13 리눅스_디바이스_드라이버_5

2022. 6. 13. 02:23BE/Linux

Makefile 연습

main.c

#include <stdio.h>

int main(void){
    printf("hello\n");
#ifdef SCULL_DEBUG
    printf("World\n");
#endif
    return 0;
}

 

Makefile

TARGET = main
SOURCE = main.c
CC = gcc

all :
    $(CC) $(SOURCE) -O2 -o $(TARGET)

clean :
    rm -f $(TARGET)

-O2 : Optimization 최적화, 최적화 레벨 2

 

  • 최적화 옵션 : 실행 파일의 크기를 줄이고, 실행 속도를 향상시킨다.
  1. -O0 : 최적화를 수행하지 않는다.
  2. -O1 : -O0보다는 높은 수준의 최적화. (= -O)
  3. -O2 : 가장 많이 사용하는 수준의 최적화. 일반 응용 프로그램이나 커널을 컴파일할 때 사용.
  4. -O3 : 가장 높은 수준의 최적화. 모든 함수를 인라인 함수와 같이 취급한다.( 되도록이면 사용을 지양)
  5. -O5 : 사이즈 최적화를 실행한다. (공간이 협소한 곳에서 사용 - 임베디드 시스템)

 

TARGET = main
SOURCE = main.c
CC = gcc

#SCULL_DEBUG=y

ifeq ($(SCULL_DEBUG), y)
    CFLAGS = -O -g -o
else
    CFLAGS = -O2 -o
endif

all :
    $(CC) $(SOURCE) $(CFLAGS) $(TARGET)

clean :
    rm -f $(TARGET)

gdb라는 디버거를 사용할 때는 위의 CFLAGS를 사용한다.

 

이유는 -O2 옵션을 사용하면 최적화를 위해서 코드의 순서가 변형되기에 -g의 이용이 불가하다.

 

그래서 디버깅 때는 위에 라인을, 디버깅이 끝나면 아래 코드를 사용하도록 한다.

 

  • 디버깅 옵션
  1. -g : gdb에게 제공하는 정보를 바이너리에 삽입한다. (-g 옵션을 사용하지 않고 gdb로 디버깅하면, 역어셈 → 어셈블리 코드로만 디버깅 가능)
  2. -pg : 프로파일을 위한 코드를 삽입한다. (-pg 옵션으로 컴파일 → gmon.out(프로파일 정보) → gprof로 gmon.out 파일 분석)

gdb는 the GNU Project debugger다.

 

출처 : https://jangpd007.tistory.com/220

출처 : https://jangpd007.tistory.com/220 [참 놀라운 세상:티스토리]


LDD example install

 

git clone https://github.com/martinezjavier/ldd3.git
cd ldd3
make

강의 시간에 사용할 예제를 다운로드한다. (뭔지는 모르겠지만 일단은 ;;)

 

/ldd3/scull/Makefile

# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y

# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
  DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
else
  DEBFLAGS = -O2
endif

LDDINC=$(PWD)/../include

EXTRA_CFLAGS += $(DEBFLAGS)
EXTRA_CFLAGS += -I$(LDDINC)

ifneq ($(KERNELRELEASE),)
# call from kernel build system

scull-objs := main.o pipe.o access.o

obj-m   := scull.o

else

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)

modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.mod modules.order *.symvers

depend .depend dep:
    $(CC) $(EXTRA_CFLAGS) -M *.c > .depend

ifeq (.depend,$(wildcard .depend))
include .depend
endif

scull

 

cd scull
ll

3개의 shell script : scull.init, scull_load, scull_unload

 


scull_load

#!/bin/sh
# $Id: scull_load,v 1.4 2004/11/03 06:19:49 rubini Exp $
module="scull"
device="scull"
mode="664"

# Group: since distributions do it differently, look for wheel or use staff
if grep -q '^staff:' /etc/group; then
    group="staff"
else
    group="wheel"
fi

# invoke insmod with all arguments we got
# and use a pathname, as insmod doesn't look in . by default
insmod ./$module.ko $* || exit 1

# retrieve major number
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)

# Remove stale nodes and replace them, then give gid and perms
# Usually the script is shorter, it's scull that has several devices in it.

rm -f /dev/${device}[0-3]
mknod /dev/${device}0 c $major 0
mknod /dev/${device}1 c $major 1
mknod /dev/${device}2 c $major 2
mknod /dev/${device}3 c $major 3
ln -sf ${device}0 /dev/${device}
chgrp $group /dev/${device}[0-3]
chmod $mode  /dev/${device}[0-3]

rm -f /dev/${device}pipe[0-3]
mknod /dev/${device}pipe0 c $major 4
mknod /dev/${device}pipe1 c $major 5
mknod /dev/${device}pipe2 c $major 6
mknod /dev/${device}pipe3 c $major 7
ln -sf ${device}pipe0 /dev/${device}pipe
chgrp $group /dev/${device}pipe[0-3]
chmod $mode  /dev/${device}pipe[0-3]

rm -f /dev/${device}single
mknod /dev/${device}single  c $major 8
chgrp $group /dev/${device}single
chmod $mode  /dev/${device}single

rm -f /dev/${device}uid
mknod /dev/${device}uid   c $major 9
chgrp $group /dev/${device}uid
chmod $mode  /dev/${device}uid

rm -f /dev/${device}wuid
mknod /dev/${device}wuid  c $major 10
chgrp $group /dev/${device}wuid
chmod $mode  /dev/${device}wuid

rm -f /dev/${device}priv
mknod /dev/${device}priv  c $major 11
chgrp $group /dev/${device}priv
chmod $mode  /dev/${device}priv

major 넘버와 minor 넘버를 할당하고 /dev 아래 디바이스 디렉터리를 만드는 과정

 

scull이 들어간 많은 디바이스들이 만들어진다.

 

➜  scull git:(master) ✗ ls -l /dev/scull*
zsh: no matches found: /dev/scull*
➜  scull git:(master) ✗ ./scull_load
➜  scull git:(master) ✗ ls -l /dev/scull*
lrwxrwxrwx 1 root root        6 Jun  7 15:39 /dev/scull -> scull0
crw-rw-r-- 1 root staff 243,  0 Jun  7 15:39 /dev/scull0
crw-rw-r-- 1 root staff 243,  1 Jun  7 15:39 /dev/scull1
crw-rw-r-- 1 root staff 243,  2 Jun  7 15:39 /dev/scull2
crw-rw-r-- 1 root staff 243,  3 Jun  7 15:39 /dev/scull3
lrwxrwxrwx 1 root root       10 Jun  7 15:39 /dev/scullpipe -> scullpipe0
crw-rw-r-- 1 root staff 243,  4 Jun  7 15:39 /dev/scullpipe0
crw-rw-r-- 1 root staff 243,  5 Jun  7 15:39 /dev/scullpipe1
crw-rw-r-- 1 root staff 243,  6 Jun  7 15:39 /dev/scullpipe2
crw-rw-r-- 1 root staff 243,  7 Jun  7 15:39 /dev/scullpipe3
crw-rw-r-- 1 root staff 243, 11 Jun  7 15:39 /dev/scullpriv
crw-rw-r-- 1 root staff 243,  8 Jun  7 15:39 /dev/scullsingle
crw-rw-r-- 1 root staff 243,  9 Jun  7 15:39 /dev/sculluid
crw-rw-r-- 1 root staff 243, 10 Jun  7 15:39 /dev/scullwuid

 

scull 실행

 

scull_load를 실행해서 /dev/scull* 파일을 생성하고 쓰고 읽어 보았다.

➜  scull git:(master) ✗ cat > /dev/scull0
hello world
^D
➜  scull git:(master) ✗ cat /dev/scull0
hello world

ctrl+D : cat 입력 종료

 

scull_unload

➜  scull git:(master) ✗ ./scull_unload
➜  scull git:(master) ✗ ls -l /dev/scull*
zsh: no matches found: /dev/scull*

'BE > Linux' 카테고리의 다른 글

2022-06-29 다중사용자, 슈퍼유저  (1) 2022.06.29
2022-06-28 Cron_실행  (0) 2022.06.28
2022-06-13 리눅스_디바이스_드라이버_4  (0) 2022.06.13
2022-06-05 리눅스_디바이스_드라이버_3  (0) 2022.06.05
2022-06-05 Makfile_이해  (0) 2022.06.05