안경잡이개발자

728x90
반응형

※ 리눅스(Linux) 커널 소스코드 다운로드 ※

 

우분투는 전형적인 데비안 리눅스 기반의 운영체제다. 가장 먼저 리눅스 커널 소스코드를 다운로드받는다. 버전별로 리눅스 커널 소스코드를 업로드해 놓은 사이트가 존재하는데, 아래 사이트에 접속하여 자신에게 필요한 버전의 소스코드를 받을 수 있다.

 

  ▶ 전체 커널 소스코드 목록: mirrors.edge.kernel.org/pub/linux/kernel/

 

필자의 경우 리눅스 5.8.7 커널 이미지를 다운로드받았다. 간단히 wget 명령어를 이용해 다운로드할 수 있다.

 

!wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.8.7.tar.gz

 

다운로드를 완료하면 .tar 확장자의 압축 파일이 생긴다. 다음의 명령을 이용하여 압축을 해제하자.

 

tar xvf linux-5.8.7.tar.gz

 

이후에 다음과 같이 리눅스(Linux) 소스코드 폴더로 이동하면 된다. 여기에 전체 커널 코드가 있다.

 

 

※ 환경설정(configuration) 파일 준비하기 ※


커널 디렉터리 내부에 들어온 뒤에는 가장 먼저 .config 파일을 생성해야 한다. 이는 커널 환경설정 파일이다. 이때 간단히 현재 자신의 커널 설정을 그대로 옮겨올 수 있다. 만약 컴파일을 진행하는 컴퓨터의 커널 설정을 그대로 적용하고자 한다면 마음과 같은 형태의 코드를 사용한다.

 

sudo cp /boot/config-{커널 버전} ./.config

 

필자는 아래와 같이 명령어를 입력하여 실행했다.

 

 

※ 커널 컴파일(Compile) 준비하기 ※

 

이어서 리눅스 커널을 컴파일하기 위해 필요한 패키지들을 설치한다. 아래 명령어는 필수 패키지 설치를 위해 일반적으로 많이 사용되는 명령어다. 가능하다면 필요하지 않은 패키지는 설치하지 않고, 패키지가 없다는 오류 메시지가 나오면 그때마다 패키지를 설치하는 방법으로 진행해도 된다.

sudo apt-get install build-essential libncurses5 libncurses5-dev bison flex libssl-dev libelf-dev bin86 kernel-package

 

※ 커널 컴파일(Compile) ※

 

컴파일 및 빌드는 생각보다 간단하다. 커널 소스코드를 수정한 뒤에 make를 입력하여 컴파일을 진행하면 된다. 이때 컴파일 속도를 빠르게 만드는 옵션을 사용할 수 있다. 이를 위해 가장 먼저 nproc 명령어를 이용하여 컴파일을 수행하는 컴퓨터의 프로세서(processor) 개수를 구하자.

 

 

필자의 경우 8코어 CPU를 사용하고 있기 때문에, -j8 옵션을 사용하겠다. 더불어 데비안 패키지(Debian Package) 형태로 빌드를 진행하겠다. 참고로 데비안 패키지는 .deb 확장자를 가지며, 비유하자면 윈도우에서의 .exe나 .msi와 같은 확장자를 가지는 프로그램 설치용 소프트웨어와 유사한 기능을 제공한다.

 

make -j8 bindeb-pkg

 

커널 컴파일을 진행해보자. 일반적인 PC에서 컴파일 명령어를 입력하면 1시간 이상의 시간이 소요될 수 있다. 대신에 한 번 컴파일했다면 그다음부터는 소스코드를 조금씩 수정해도 비교적 금방 컴파일이 완료될 것이다.

 

 

다음의 사진과 같이 매우 많은 소스코드를 컴파일하게 되는 것을 알 수 있다.

 

 

컴파일이 완료되고 .deb 패키지들이 생겼다.

 

 

대략 다음과 같은 형태의 데비안 패키지들을 얻었다면 성공이다.

 

linux-headers-5.8.7_5.8.7-4_amd64.deb
linux-image-5.8.7_5.8.7-4_amd64.deb
linux-libc-dev_5.8.7-4_amd64.deb

 

※ 패키지 옮기기 ※

 

필자의 경우에는 컴파일을 수행한 컴퓨터가 아닌 다른 컴퓨터의 커널을 업데이트할 것이다. 따라서 일단 데비안 패키지를 커널을 업데이트할 컴퓨터의 저장장치로 옮기면 된다.

 

그러므로 일단 커널을 업데이트할 저장장치를 연결한 뒤에 마운트를 진행한다.

 

mkdir -p mnt/fat32
mkdir -p mnt/ext4
sudo mount {블록 디바이스} mnt/fat32
sudo mount {블록 디바이스} mnt/ext4

 

 

이제 cp 명령어를 이용하여 .deb 파일을 옮긴다.

 

cp linux-headers-5.8.7_5.8.7-4_amd64.deb mnt/ext4/home/
cp linux-image-5.8.7_5.8.7-4_amd64.deb mnt/ext4/home/
cp linux-libc-dev_5.8.7-4_amd64.deb mnt/ext4/home/

 

패키지(package) 파일을 모두 옮겼다면 마운트를 해제하면 된다.

 

sync
sudo umount mnt/fat32
sudo umount mnt/ext4
rm -rf mnt/

 

 

※ 커널 업데이트 ※

 

모든 .deb 파일을 옮겼다면, 커널을 업데이트할 컴퓨터를 실행한 뒤에 dpkg 명령어를 이용하여 패키지를 설치한다.

 

sudo dpkg -i linux-headers-5.8.7_5.8.7-4_amd64.deb
sudo dpkg -i linux-image-5.8.7_5.8.7-4_amd64.deb
sudo dpkg -i linux-libc-dev_5.8.7-4_amd64.deb

 

설치가 완료되었다면 재부팅한다.

 

sudo reboot

 

 

※ 참고사항 ※

 

커널이 정상적으로 업데이트되었는지 확인하기 위해 커널 정보를 출력할 수 있다.

 

cat /proc/version

 

728x90
반응형

728x90
반응형

이 포스팅에는 부정확한 내용이 존재할 수 있습니다. Disk Identifier를 잘못 건드리면 파일 시스템에 문제가 생겨 부팅 자체에 실패할 수 있으며, 본 블로그의 글을 따라 하여 발생하는 문제에 대한 책임은 지지 않습니다.

 

※ 문제 상황 ※

 

  우리는 dd와 같은 명령어를 이용해 특정 디스크 내용 전체를 다른 디스크로 복제할 수 있다. 다만 이때 기본적으로 디스크(disk)의 식별자(identifier)도 복제된다. 만약 원본 디스크와 복제된 디스크를 둘 다 하나의 컴퓨터에 연결하여 부팅하게 되면 어떤 문제가 발생할 수 있을까? 다시 말해 디스크 식별자(disk identifier)가 완전히 동일한 두 개의 장치가 있을 때 부팅을 시도하는 것이다.

 

  이렇게 하면 UEFI를 위한 GPT가 올라가 있는 파티션Linux OS가 올라가 있는 파티션서로 다른 디스크(저장장치)로부터 인식하게 되는 문제가 발생할 수 있다.

 

  아래 그림은 SD 카드(mmcblk2)에 있는 디스크와 USB(sda)에 있는 디스크가 완전히 동일한 상황에서 부팅을 한 결과다. 분명히 SD 카드로 부팅을 시도했지만, GPT 부분만 정상적으로 SD 카드에 있는 파티션을 통해 인식했다. 실제로 리눅스(Linux) 파일 시스템에 대해서는 USB에 있는 파티션을 이용해 부팅을 진행한 것이다.

 

  즉, SD 카드로 부팅을 했는데 정작 USB에 있는 OS를 불러와 사용하고 있는 것이다. 디스크의 식별자가 동일하기 때문에 발생하는 문제다.

 

 

  만약에 SD 카드만 꽂혀 있거나, USB만 꽂혀 있는 경우에서는 당연히 정상적으로 하나의 디스크만 사용하여 부팅을 진행할 수 있다. 하지만 이처럼 동일한 식별자(identifier)를 가지는 두 개의 디스크가 동시에 꽂혀 있다면 OS를 부팅하는 과정에서 문제가 발생할 수 있다.

 

※ 문제의 원인 ※

 

  이러한 문제는 왜 발생하는 걸까? 앞서 말했듯이 디스크의 식별자가 동일하기 때문이다. 특히 GPT에 있는 GRUB과 관련이 있다. GRUB은 부트로더(bootloader)로서 불러올 OS가 존재하는 저장장치에 대한 정보를 환경설정 파일 형태로 미리 가지고 있을 수 있다.

 

  SD 카드로 부팅을 진행하게 되면, GPT 영역을 참조하여 미리 정해진 OS 파티션의 디스크로 실제 부팅을 진행한다. 이때 디스크 UUID가 중복되는 경우에는 UEFI 레벨에서 부팅하기로 설정한 저장장치(SD 카드)가 아닌 (USB와 같은) 다른 저장장치를 이용해 부팅을 진행할 수 있다는 것이다.

 

※ UUID 확인해 보기 ※

 

  이러한 문제를 해결하기 위해 하나의 디스크의 UUID를 변경하는 시도를 해보자. 그러기 전에 가장 먼저 blkid 명령어를 이용하여 UUID를 포함한 구체적인 저장장치 정보를 확인할 수 있다. (sudo blkid | grep UUID) 확인해 보면 sda와 mmcblk2p의 UUID가 정확히 동일한 것을 알 수 있다. 이러한 상황에서는 문제가 발생할 수 있는 것이다.

 

 

※ 해결 과정 ※

 

  문제를 해결하기까지 시도한 내용에 대하여 차근차근 명시하겠다.

 

[과정 1] tune2fs 명령어를 이용한 ext4 파티션 UUID 변경

 

  먼저 tune2fs에 대하여 알아보자. tune2fs는 리눅스 파일시스템의 다양한 변수 값을 바꿀 수 있도록 도와주는 명령어다. 한 번 OS가 존재하는 ext4 형식에 해당하는 /dev/mmcblk2p2 디바이스의 UUID를 변경해보겠다.

 

 

  성공적으로 변경된 것을 확인할 수 있다. /dev/mmcblk2p2의 UUID 부분이 새로운 값으로 변경되었다.

 

 

  이는 ext4 형식의 파일 시스템의 UUID를 변경하는 전형적인 방법이다. 또한, 이처럼 UUID를 변경하는 경우에는 fstab에서 이전 UUID 레이블(label) 정보를 가지고 있는지 확인할 필요가 있다. 따라서 UUID를 변경한 장치를 마운트한 뒤에 해당 UUID가 변경된 디바이스 내부의 /etc/fstab 파일을 열어서 ext4에 해당하는 UUID 값을 변경된 값에 맞게 수정해준다.

 

  이때 fstab파일시스템 정보를 담고 있는 설정 파일이다. 그러므로 부팅 시 UUID가 잘못 기록되어 있으면 grub까지만 진입하게 되며 OS를 정상적으로 부팅할 수 없게 된다.

 

 

  다만 여기까지 한다고 하더라도 재부팅을 진행했을 때 grub 단계에서 오류가 발생하고 OS 부팅으로 넘어가지 못하는 문제가 발생할 수 있다. 특히 필자의 경우 UUID를 바꾼 디바이스를 그 자체로 저장장치로 사용해야 하기 때문에 grub 단계에서 넘어가지 못하면 의미가 없었다.

 

[과정 2] grub.cfg 파일 수정

 

  말했듯이 fstab을 변경했다고 해도 여전히 grub 단계에서 다른 장치로 부팅을 시도하기 때문에, SD 카드로 부팅을 하였을 때 (USB 장치에서 OS를 불러오거나 하는) 오류가 발생할 수 있다. 따라서 grub 환경설정(configuration) 파일을 수정할 필요가 있다. 따라서 마찬가지로 UUID를 변경한 디바이스(device)를 마운트한 뒤에 /boot/grub/grub.cfg 파일을 수정한다.

 

  참고로 vi 에디터(editor)를 사용하면 다음과 같은 형식의 명령어를 이용해 문서 전체에서 특정 문자열을 다른 문자열로 바꿀 수 있다.

:%s/{변경할 문자열}/{변경 이후 문자열}/g


  필자는 다음과 같이 입력하여 일괄적으로 UUID를 변경했다.

:%s/6355c332-3454-4cbd-9a91-f4100bac43bf/fe0f0275-24f3-4a5c-8551-80ec4fa8cae7/g

 

  변경 결과는 다음과 같다. 이제 문서를 저장하고 나온다.

 

 

[과정 3] GPT 파티션의 grub.cfg 수정


  또한 GPT 파티션에도 이전 UUID 값이 기록되어 있는지 확인할 필요가 있다.

 

 

  그래서 필자는 UUID를 변경한 저장장치의 GPT 파티션을 마운트하여 /EFI/ubuntu/grub.cfg를 확인했다. 마찬가지로 여기에서도 UUID에 대한 값이 하드코딩되어 있었다. 그래서 이 값 또한 변경된 UUID가 들어갈 수 있도록 하였다.

 

 

  이제 마운트를 해제하고 재부팅을 진행한다. 그러면 정상적으로 SD 카드로 오류 없이 부팅이 완료된다. 참고로 여기까지의 과정을 수행하여 SD 카드와 USB를 완전히 구분할 수 있게 되었다는 것은, GPT 파티션의 UUID가 같아도 UEFI 레벨에서는 이 두 개를 구분할 수 있다는 의미가 된다.

 

[추가적인 시도] hexedit {/dev/example}

 

  그래도 아직 UEFI 관련 파티션의 UUID는 변경되지 않았다. 그래서 UEFI 파티션의 UUID를 바꾸기 위한 방법을 생각해 보다가 HEX 데이터를 변경하여 수정하는 방법을 진행해 보았다. UUID 값이 "EB93-49AC"라고 되어 있으므로, /를 눌러 "AC4993EB"를 검색했다.

 

 

이후에 해당 내용을 내가 원하는 문자열로 바꾸었다. 간단히 "12123434"로 바꾸어 볼 수 있을 것이다.

 

 

결과적으로 이번 시도에서는 다시 blkid 명령어를 사용했을 때 성공적으로 UUID가 변경된 것을 확인할 수 있었다.

 

 

  다만 이렇게 바꾸고 나서도 UEFI 레벨에서 저장장치의 UUID를 확인할 때는 여전히 변경되기 전의 UUID로 인식되고 있는 것을 알 수 있었다. 다시 말해 이 부분은 해결하지 못했다.

728x90
반응형