반응형
작성일: 2026년 3월 5일

 

 

Linux kernel source code를 다운로드하기

git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

 

위 git 명령은 최신 mainline 코드를 가져온다.

방금 다운로드한 kernel version을 확인하려면, Makefile을 열어서 파일 내용의 위 5줄을 읽어야 한다.

$ cat Makefile

VERSION = 7
PATCHLEVEL = 0
SUBLEVEL = 0
EXTRAVERSION = -rc2
NAME = Baby Opossum Posse

... 중간 생략 ...

 

만약 특정 version의 kernel source  code를 가져와서 build하고 싶다면, 아래 예시와 같이 `git fetch` 명령을 실행해야 한다. 

$ git fetch origin tag v6.19 --no-tags
$ git checkout v6.19

## 또는 아래와 같이 처음부터 `git clone`할 때, 특정 tag를 지정해서 가져온다.
$ git clone --depth 1 --branch v6.19 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux-6.19

 

Kernel source code를 build하기 위해 필요한 utility program을 설치하기

sudo apt install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev libdw-dev dwarves bc pkg-config rsync cpio zstd

 

Kernel source code를 Compile하기

`make menuconfig` 명령을 실행하여 필요한 빌드 옵션을 On/Off 설정한다.

`make munuconfig` 화면에서 build option을 설정했으면, Signature 체크용 인증서 정보를 삭제한다. (아래 명령을 참고)

./scripts/config --set-str SYSTEM_TRUSTED_KEYS "" --set-str SYSTEM_REVOCATION_KEYS ""

 

 

`make` 명령을 수행한다.

source code 분량이 많기 때문에 -j 옵션을 추가하여 make 명령을 수행해야 한다.

-j 옵션이 없는 상태로 compile하면, 하루 종일 build해야 한다.

make -j$(nproc)

또는 

make -j2

 

 

Tip: 참고할 내용

Kernel source code Build에 걸리는 시간:

[ CPU 8 Core를 사용할 때 ]

  - HW 사양: Intel i7-11700 @ 2.50GHz

  - Build time: 32분 걸림

[ CPU 1 Core를 사용할 때 ]

  - HW 사양: Intel i7-11700 @ 2.50GHz

  - Build time: 3시간 40분 걸림

 

Build된 kernel binary file을 Machine에 적용하는 방법

1. Module 설치

sudo make modules_install

위 명령은 .ko module file을 /lib/modules/6.19.0/ 같은 directory에 복사한다.

 

2. Kernel 설치 (Kernel image 복사, Grub 설정 변경)

sudo make install

위 명령은 bzImage 파일과 System.map 파일을 /boot directory에 복사하고

Ubuntu/Debian 같은 배포판 리눅스에서는 /sbin/installkernel 스크립트를 이용하여 initramfs 파일을 생성하고 update-grub 절차까지 수행한다.

 

3. Reboot 후 새 kernel 선택

sudo reboot

컴퓨터가 reboot되면서, GRUB 화면이 보일 것이다.

이때 [ Advanced options ] - [ Linux 6.19.0 ] 을 선택하고, OS booting 과정을 진행하면 된다.

 

4. 새 kernel 적용 여부 확인

$ uname -r
6.19.0-11-generic

 

내가 build한 kernel version과 같은지 확인한다.

반응형
작성일: 2025년 1월 10일

 

Linux kernel source code를 다운로드하는 방법

GitHub에서 Git Clone하기

$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

 

참고: github에서 clone하면, 다운로드 시간이 엄청 길다. 내 경우는 10분 소요되었다.

 

 

Tar 파일로 다운로드하기

아래 Linux Kernel 공식 Archive 홈페이지에서 원하는 Linux 버전의 소스 코드에 대한 Tar 파일을 다운로드.

https://www.kernel.org

 

 

반응형

 

작성일: 2024년 12월 10일

 

 

Segmentation fault (core dumped)

 

분명 process가 segmentation fault 상황에서 core file이 dump되어야 하는데, 어디에도 core file이 없는 경우가 있다.

이럴 때는 coredump와 관련한 설정이 안 되어 있는 것이니까, 아래의 내용을 보고 coredump 관련 설정이 잘 되어 있는지 다시 확인해봐야 한다.

 

core dump file의 size 제한 설정이 있는지 확인

너무 큰 core dump file이 생성되는 부작용을 막기 위해 core file size limit 설정이 존재한다.

(2020년대 이후로는 SSD, HDD가 충분히 커서 이런 core file size limit이 유용한지 모르겠다.)

core file이 수십개가 dump되어도 문제 없을만큼 storage가 크다면, unlimit 설정값으로 바꾸는 것을 권장한다.

## 현재 설정값 확인하는 명령.
$ ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) unlimited
data seg size               (kbytes, -d) unlimited
... (내용 생략) ...

## core file size 제한을 푸는 명령 (무제한 크기로 변경)
$ ulimit -c unlimited

 

위와 같이 설정하면, 내 login shell 환경에만 즉시 적용되고  Linux 시스템 전체적으로는 아직도 옛날 core file size가 적용된다.

따라서 Linux 시스템 전체에 설정 값을 적용하려면 아래와 같이 limits.conf 파일을 수정해야 한다.

$  cat  /etc/security/limits.conf
(... 중간 내용 생략 ...)
*      soft    core      unlimited
(... 중간 내용 생략 ...)

 

 

core file 이름 패턴 및 경로 설정

core file이 어느 폴더에 저장되고, 어떤 이름으로 저장될지 설정해야 한다.

$ cat /proc/sys/kernel/core_pattern
/tmp/core.%e.%p.%h.%t

 

각 설정값이 의미하는 것은 이렇다.

  • %e   프로그램 이름 (실행 binary file name)
  • %p   Process ID (예: 3453)
  • %h   Host name (예: mynode)
  • %t    core file dump된 시각 

 

위와 같이 설정하면, 아래와 같이 실제로 core file이 /tmp 폴더에 dump된다.

$ ls /tmp/core.*
/tmp/core.myapp.104618.mynode.1733790395

 

위 파일 이름에 포함된 "1733790395" 값은 Unix time(또는 epoch time)라고 한다.

이 epoch time을 우리 눈에 익숙한 포맷으로 바꾸려면 아래와 같이 명령을 수행하면 된다.

## Timezone 설정이 UTC이면, 아래와 같이 출력 
$ date -d @1733790395
Tue 10 Dec 00:26:35 UTC 2024

## Timezone 설정이 Asia/Seoul이면, 아래와 같이 출력
$ date -d @1733790395
Tue Dec 10 09:26:35 KST 2024

 

 

epoch time 및 date 포맷 변경에 관한 자세한 내용은 아래 블로그 글을 참고

https://andrewpage.tistory.com/193


 

반응형
작성일: 2024년 8월 14일

 

 

CPU 온도 모니터링

$ apt install lm-sensors

$ sensors-detect --auto

$ systemctl restart module-init-tools

$ watch sensors

 

 

프로세스 별 Network traffic 모니터링

$ apt install nethogs

$ nethogs eth0

$ apt install iftop

$ iftop -i eth0

 

 

 

 

 

 

 

 

 


 

반응형

 

 

https://www.x-plane.com/desktop/try-it/

 

Try It - X-Plane

The X-Plane 11 beta is here! Download the X-Plane 11 demo today, for free. Available for macOS, Windows, and Linux.

www.x-plane.com

 

 

https://www.flightgear.org/

 

FlightGear Flight Simulator – sophisticated, professional, open-source

Current stable release: 2020.3.18 – released 21/03/2023 This is our current well-tested and supported version for most users. Announcements 21st March 20202:  release 2020.3.18 is out. This includes an over-hauled generic autopilot and support for ortho

www.flightgear.org

 

반응형

"커널연구회"의 자료를 참고!

 

 

https://www.kernel.bz/blogPost/kernel-mov-list

 

커널 소스 분석 문서 및 동영상 강의 목록

 

kernel.bz

 

 

http://www.iamroot.org/

 

iamroot.org - IT 스터디

kernel, xen, kvm, gcc, ai 스터디 그룹

www.iamroot.org

 

 

http://www.iamroot.org/xe/index.php?mid=Study&document_srl=215076 

 

커널 스터디를 위한 문c 가이드입니다. - 스터디 - iamroot.org

안녕하세요? 문c 블로그(http://jake.dothome.co.kr)의 문영일입니다.   한 달 후면 여러분들이 1년간 기다리셨던 18차 커널 스터디가 시작됩니다. 커널 스터디를 통한 과실은 이미 많은 분들이 들어보

www.iamroot.org

 

 

http://jake.dothome.co.kr/

 

문c 블로그

최신 ARM 리눅스 5.x 커널 분석

jake.dothome.co.kr

 

 

 


 


https://hyeyoo.com/80

 

[kernel/locking] spinlock (1) - spinlock 사용법

앞선 글에서 lock이란 무엇이고, lock의 필요성에 대해서 알아보았다. 이번 글에서는 가장 기본적인 spinlock을 리눅스 커널에서 어떻게 구현했는지 알아볼 것이다. 우선 관련된 개념을 몇 가지 살펴

hyeyoo.com

 

 

https://pr0gr4m.github.io/

 

Linux Kernel Analysis

Linux Kernel Blog

pr0gr4m.github.io

 

반응형

 

 

 

참고 문서:
  "문c 블로그 - RCU(Read Copy Update)"
  http://jake.dothome.co.kr/rcu/

 

 

참고 문서: 
  "리눅스 커널 RCU 이해 / 커널연구회"
  https://kernel.bz/boardPost/118679/20

 

반응형

 

C language, Go(Golang), Netfilter, Netlink를 이용하여 Linux network을 제어하고 모니터링하는 방법을 알아보자~

 

 

개념 이해하기: Netfilter hooks into Linux networking packet flows

The following schematic shows packet flows through Linux networking:

 

From:  https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks

 

 


Linux Netfilter + C example code

참고 문서:   https://pr0gr4m.github.io/linux/kernel/netfilter/
  이론 설명과 함께 잘 동작하는 예시가 있어서 쉽게 이해할 수 있다.
  아래는 위 블로그의 끝 부분에 있는 HTTP Traffic만 선별하여 Drop하는 예제 코드인데,
  그냥 이 예제 코드만 봐도 이해할 수 있을 것이다.

 

http_netfilter.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netdevice.h>

static unsigned int hook_http(void *priv,
		struct sk_buff *skb, const struct nf_hook_state *state)
{
	struct iphdr *iph;
	struct tcphdr *th;
	char *data = NULL;
	int length = 0;
	
	if (!skb)
		return NF_ACCEPT;

	iph = ip_hdr(skb);

	if (iph->protocol == IPPROTO_TCP) {
		th = tcp_hdr(skb);

		length = skb->len - iph->ihl * 4 - th->doff * 4;
		if (length <= 4)
			return NF_ACCEPT;

		data = kzalloc(length, GFP_KERNEL);
		memcpy(data, (unsigned char *)th + th->doff * 4, length);

		if (strstr(data, "HTTP") != NULL) {
			printk("[Kernel:%s] HTTP Detected\n", __func__);
			kfree(data);
			return NF_DROP;
		}

		kfree(data);
	}

	return NF_ACCEPT;
}

static struct nf_hook_ops *nf_ops = NULL;

static int __init nfilter_init(void)
{
	nf_ops = (struct nf_hook_ops *)kzalloc(sizeof(struct nf_hook_ops), GFP_KERNEL);
	nf_ops->hook = (nf_hookfn *)hook_http;
	nf_ops->pf = PF_INET;
	nf_ops->hooknum = NF_INET_LOCAL_IN;
	nf_ops->priority = NF_IP_PRI_FIRST;

	nf_register_net_hook(&init_net, nf_ops);
	printk("[Kernel:%s] NFilter Init\n", __func__);
	return 0;
}

static void __exit nfilter_exit(void)
{
	nf_unregister_net_hook(&init_net, nf_ops);
	kfree(nf_ops);
	printk("[Kernel:%s] NFilter Exit\n", __func__);
}

module_init(nfilter_init);
module_exit(nfilter_exit);
MODULE_LICENSE("GPL");

 

Makefile

obj-m += http_netfilter.o

KDIR := /lib/modules/$(shell uname -r)/build

default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

CC := gcc

%.c%:
	${CC} -o $@ $^

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
	rm -f ${TARGETS}

 

Build & Test

##
## HTTP Server 장비에서 아래 명령을 수행.
##

$ make

$ sudo insmod http_netfilter.ko

$


---

##
## 다른 PC에서 아래와 같이 HTTP Traffic을 발생시켜본다.
##
$ curl -v http://my-test.server.domain/

*   Trying my-test.server.domain:80...
* Connected to my-test.server.domain port 80 (#0)
> GET / HTTP/1.1
> Host: my-test.server.domain
> User-Agent: curl/7.77.0
> Accept: */*
> ##
## TCP Session만 수립될 뿐, 
## 실제 HTTP Response 패킷을 받지 못해서 이 상태로 계속 남아있다가 Timed out 처리된다.
##
* Recv failure: Operation timed out
* Closing connection 0
curl: (56) Recv failure: Operation timed out
$


---

##
## HTTP Server 장비에서 아래 명령을 수행.
##

$ dmesg --color --follow
... 중간 생략 ..
[264707.035282] [Kernel:hook_http] HTTP Detected
[264711.387549] [Kernel:hook_http] HTTP Detected
... 중간 생략 ..

 

 

 

 

 

 


Netlink for C language

Wikipedia

Netlink Protocol Library Suite (libnl)

Core Library Developer's Guide (libnl)

Routing Library Developer's Guide (libnl-route)

Example Collection

 

 

 

위 문서를 읽고 나서, 아래 예제를 테스트하면서 이해하기.

$  cat detect_chg_event.c


/**
 * How to build
 *   $  gcc -o detect_chg_event detect_chg_event.c
 * How to run
 *   $  ./detect_chg_event
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>


static int
create_sock (const char *nic)
{
    struct sockaddr_nl addr;
    int                sock;

    memset (&addr, 0, sizeof (addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;

    sock = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock < 0)
    {
        fprintf (stderr, "failed to open NETLINK_ROUTE socket for %s - %s(%d)",
                nic, strerror (errno), errno);
        return -1;
    }

    if (bind (sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        fprintf (stderr, "failed to bind NETLINK_ROUTE socket for %s - %s(%d)",
                nic, strerror (errno), errno);
        close (sock);
        return -1;
    }

    return sock;
}


/**
 * NOTE: Cheeck if NIC status is changed
 */
static int
ip_changed (int         sock,
			const char *nic)
{
    struct nlmsghdr   *nlh;
    char               buffer[4096];
    int                len;
    int                idx;
    int                found;

    len = recv (sock, buffer, sizeof (buffer), 0);
    if (len <= 0)
    {
        fprintf (stderr, "NETLINK_ROUTE socket recv() failedn");
        return -1;
    }

    printf("\n %s %s(%d) Receive message from raw socket \n",
            __func__, __FILE__, __LINE__);

    found = 0;
    idx = if_nametoindex (nic);

    printf("\n %s %s(%d) Index of %s: %d \n",
            __func__, __FILE__, __LINE__, nic, idx);

    for (	nlh = (struct nlmsghdr *) buffer;
            NLMSG_OK (nlh, len);
            nlh = NLMSG_NEXT (nlh, len))
    {
        if (nlh->nlmsg_type == NLMSG_DONE)
            break;
        if (nlh->nlmsg_type == NLMSG_ERROR)
            continue;
        if (!(NLMSG_OK (nlh, len)))
            continue;

        printf("\n %s %s(%d) Netlink MSG Type: %d\n",
                __func__, __FILE__, __LINE__, nlh->nlmsg_type);

        /*
         * NOTE:
         *   RTM_NEWADDR, RTM_NEWLINK 에 관한 정의는 rtnetlink.h 파일에서 확인할 수 있다.
         *     - /usr/include/linux/rtnetlink.h
         */
        switch (nlh->nlmsg_type)
        {
            case RTM_NEWADDR:
                {
                    struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nlh);

                    if (ifa->ifa_index == idx)
                        found = 1;
                }
                break;
            case RTM_NEWLINK:
                {
                    struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA (nlh);

                    if (ifi->ifi_index == idx)
                        found = 1;
                }
                break;
            default:
                break;
        }
    }

    return found;
}


static int
get_nic_addr (  const char     *nic,
				struct ifaddrs *ifaddr,
				int             wanted_family,
				char           *host,
				int             host_len,
				int            *active)
{
    struct ifaddrs *ifa;

    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
    {
        int family;
        int s;

        if (ifa->ifa_addr == NULL)
            continue;

        if (strcmp (ifa->ifa_name, nic))
            continue;

        /* Skip unwanted families. */
        family = ifa->ifa_addr->sa_family;
        if (family != wanted_family)
            continue;

        *active = (ifa->ifa_flags & IFF_RUNNING) ? 1 : 0;

        s = getnameinfo (   ifa->ifa_addr,
                            family == AF_INET ? sizeof (struct sockaddr_in) :
                            sizeof (struct sockaddr_in6),
                            host,
                            host_len,
                            NULL,
                            0,
                            NI_NUMERICHOST);
        if (s != 0)
        {
            fprintf (stderr, "failed to getnameinfo() for '%s - %s(%d)",
                    ifa->ifa_name, strerror (errno), errno);
            continue;
        }

        /* Get the address of only the first network interface card. */
        return 1;
    }

    return 0;
}


static void
print_ip (const char *nic)
{
    struct ifaddrs *ifaddr;
    char            addr[NI_MAXHOST];
    int             active;

    printf("\n %s(%d) nic: %s \n",
            __FILE__, __LINE__, nic);

    if (getifaddrs (&ifaddr) == -1)
    {
        fprintf (stderr, "failed to getifaddrs() - %s(%d)", strerror (errno), errno);
        return;
    }

    // NOTE: IPv4
    if (!get_nic_addr (nic, ifaddr, AF_INET, addr, sizeof (addr), &active))
    {
        // If IPv4 configuration is not available,
        // then try to get the Ipv6 configuration.
        printf("\n %s(%d) nic: %s  addr: %s  active: %d \n",
                __FILE__, __LINE__, nic, addr, active);
        // NOTE: IPv6
        if (!get_nic_addr (nic, ifaddr, AF_INET6, addr, sizeof (addr), &active))
        {
            // Nothing to do.
            strcpy (addr, "127.0.0.1");
            active = 0;
        }
    } else {
        printf("\n %s(%d) nic: %s  addr: %s  active: %d \n",
                __FILE__, __LINE__, nic, addr, active);
    }

    freeifaddrs (ifaddr);

    printf("\n %s %s(%d) %s is %s (link %s) \n",
            __func__, __FILE__, __LINE__,
            nic, addr, active ? "active" : "inactive");
}


int
main (void)
{
    // FIXME: enp7s0 --> my machine's network interface name
    char *nic = "enp7s0";
    int   sock;

    print_ip (nic);

    sock = create_sock (nic);
    if (sock < 0)
        return -1;

    while (1)
    {
        int ret;

        ret = ip_changed (sock, nic);
        if (ret < 0)
            return -1;

        if (ret)
            print_ip (nic);

        printf("\n\n %s %s(%d) END OF LOOP \n\n\n",
                __func__, __FILE__, __LINE__);
    }

    close (sock);

    return 0;
}


$

$  gcc -o detect_chg_event detect_chg_event.c

$  ./detect_chg_event

ip_changed detect_chg_event.c(73) Receive message from raw socket

 ip_changed detect_chg_event.c(79) Index of enp7s0: 2

 ip_changed detect_chg_event.c(93) Netlink MSG Type: 16

 detect_chg_event.c(181) nic: enp7s0

 detect_chg_event.c(205) nic: enp7s0  addr: 10.1.4.51  active: 1

 print_ip detect_chg_event.c(211) enp7s0 is 10.1.4.51 (link active)


 main detect_chg_event.c(239) END OF LOOP
 
 ...
 ...

 

위 예제에서 detect_chg_event 명령을 실행시켜 놓고, 아래와 같이 명령을 실행해본다.

$  ifconfig  enp7s0  mtu 1501
$  ifconfig  enp7s0  mtu 1500
$  ifconfig  enp7s0  down
$  ifconfig  enp7s0  up

detect_chg_event 예제 앱이 enp7s0 장치의 상태 변화를 감지해서 터미널에 감지한 내용을 출력해줄 것이다.

 

Netlink library for go

https://github.com/vishvananda/netlink

 

 


 

 

https://tomdnetto.net/post/linux_networking_from_go_nftables

 

Linux Networking From Go

Manipulating network interfaces, firewalling, and forwarding from Go.

tomdnetto.net

 

 

https://tomdnetto.net/post/advanced_nftables_with_go

 

Advanced NFTables With Go

NFTables like your mama taught you.

tomdnetto.net

 

 

 

+ Recent posts