카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2019/01/04

debootstrap arm64 qemu 설치

debootstrap arm64
1)
-- foreign 패키지 다운로드.
-- chroot 사용
-- --second-stage + QEMU 사용자 모드 에물레이션 사용.(binfmt_misc)

2) 커널 vfs 패닉
[    0.773665] Please append a correct "root=" boot option; here are the available partitions:
[    0.774033] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
파일 시스템 지원 확인.

CONFIG_VIRTIO_BLK=y

initrd에서 모듈이 로드되어야 하기 때문에 ISO 이미지를 사용해서 동작 시켜야 할 듯 함.

다른 유형의 파일시스템 유형을 사용하려고 시도했지만 커널 지원 문제가 있어, 커널 컴파일을 해야함.
-drive if= -M virt

데비안 계열 우분투 패키지 커널을 사용할 때 arm64 커널 빌드 명령어.
처음 빌드 시
export ARCH=arm64
export $(dpkg-architecture -aarm64); export CROSS_COMPILE=aarch64-linux-gnu-

fakeroot debian/rules clean
debian/rules build
fakeroot debian/rules binary

두번째 이상 빌드시.
rm debian/stamps/stamp-build*
debian/rules build
fakeroot debian/rules binary

커널 설정 옵션에서 개발자 모드를 활성화.
Ubuntu devs, CONFIG y

인터넷 동작 문제.
systemctl status dhclient.service
cat f

자동 설치 스크립트
#!/usr/bin/env bash

# https://askubuntu.com/questions/281763/is-there-any-prebuilt-qemu-ubuntu-image32bit-online/1081171#1081171

set -eux

debootstrap_dir=debootstrap
root_filesystem=debootstrap.ext2.qcow2

sudo apt-get install \
  gcc-aarch64-linux-gnu \
  debootstrap \
  libguestfs-tools \
  qemu-system-aarch64 \
  qemu-user-static \
;

if [ ! -d "$debootstrap_dir" ]; then
  sudo debootstrap \
    --arch arm64 \
    --foreign \
    bionic \
    "$debootstrap_dir" \
    http://ports.ubuntu.com/ubuntu-ports \
  ;
  sudo mkdir -p "${debootstrap_dir}/usr/bin"
  sudo cp "$(which qemu-aarch64-static)" "${debootstrap_dir}/usr/bin"
  sudo chroot "$debootstrap_dir" /debootstrap/debootstrap --second-stage
  sudo rm -f "$root_filesystem"
fi

linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"

if [ ! -f "$root_filesystem" ]; then
  # Set root password.
  echo 'root:root' | sudo chroot "$debootstrap_dir" chpasswd

  # Remount root filesystem as rw.
  cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF

  # https://askubuntu.com/questions/1045278/ubuntu-server-18-04-temporary-failure-in-name-resolution/1080902#1080902
  cat << EOF | sudo tee "${debootstrap_dir}/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF
  sudo ln -sf "${debootstrap_dir}/etc/systemd/system/dhclient.service" \
    "${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"

  # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
  sudo chmod +r "${linux_image}"

  # Generate image file from debootstrap directory.
  # Leave 1Gb extra empty space in the image.
  sudo virt-make-fs \
    --format qcow2 \
    --size +1G \
    --type ext2 \
    "$debootstrap_dir" \
    "$root_filesystem" \
  ;
  sudo chmod 666 "$root_filesystem"
fi

# 커널 컴파일.
linux_image="$(pwd)/linux/debian/build/build-generic/arch/arm64/boot/Image"
if [ ! -f "$linux_image" ]; then
  #git clone --branch Ubuntu-4.15.0-20.21 --depth 1 git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git linux
  cd linux
  cat << EOF | patch -p1
diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu
index 5ff32cb997e9..8a190d3a0299 100644
--- a/debian.master/config/config.common.ubuntu
+++ b/debian.master/config/config.common.ubuntu
@@ -10153,7 +10153,7 @@ CONFIG_VIDEO_ZORAN_ZR36060=m
 CONFIG_VIPERBOARD_ADC=m
 CONFIG_VIRTIO=y
 CONFIG_VIRTIO_BALLOON=y
-CONFIG_VIRTIO_BLK=m
+CONFIG_VIRTIO_BLK=y
 CONFIG_VIRTIO_BLK_SCSI=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_VIRTIO_INPUT=m
EOF
  export ARCH=arm64
  export $(dpkg-architecture -aarm64)
  export CROSS_COMPILE=aarch64-linux-gnu-
  fakeroot debian/rules clean
  debian/rules updateconfigs
  fakeroot debian/rules DEB_BUILD_OPTIONS=parallel=`nproc` build-generic
  cd -
fi

#linux_image=/home/ciro/bak/git/linux-kernel-module-cheat/out/linux/default/aarch64/arch/arm64/boot/Image
#linux_image=/home/ciro/bak/git/linux-kernel-module-cheat/submodules/linux/debian/build/build-generic/arch/arm64/boot/Image
qemu-system-aarch64 \
  -append 'console=ttyAMA0 root=/dev/vda rootfstype=ext2' \
  -device rtl8139,netdev=net0 \
  -drive "file=${root_filesystem},format=qcow2" \
  -kernel "${linux_image}" \
  -m 2G \
  -netdev user,id=net0 \
  -serial mon:stdio \
  -M virt,highmem=off \
  -cpu cortex-a57 \
  -nographic \
;

Linux 커널 exec의 시스템 호출 ELF 방식에서 스크립트 언어 #! 인식 shebang 지정.

Linux 커널 exec의 시스템 호출 #! 인식 shebang 지정.
#! 사람이 읽기 편하도록 구성한다는 의미(스크립트 언어)

./something

리눅스 커널 소스
linux/fs/binfmt_script.c

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
바이트를 읽은  후 비교.

참이면 커널에서 파싱.
경로 /usr/bin/env python 첫 번째 인수 사용하여 또 다른 exec 호출 생성.
/usr/bin/env python /path/to/script.py

#주석 문자 사용하는 모든 스크립팅 언어에서 동작 함.

무한 루프도 만들 수 있음.
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

bash 오류 인식
-bash: /a: /a: bad interpreter: Too many levels of symbolic links

ELF 실행 파일
linux/fs/binfmt_elf.c
magic.elfmag[EI_MAG0] = ELFMAG0;
바이트 검사. 7f 45 4c 46, 사람이 읽을 수 있으나 이해 하려면 시간이 걸림.
EFL 형식의 파일을 읽고, 메모리에 정확하게 넣고, 새로운 프로세스 시작.

debootstrap이란?

debootstrap이란?

x86 시스템에서 임베디드 ARM 또는 PowerPC 시스템용 데비안/우분투를 설치를 의미, 조금더 큰 의미에서는 네트워 부팅도 여기에 속 할 수 있음, 요즘 클라우드 컴퓨팅 환경 구성이 과도기를 지나 완성도를 높이는 단계로 진입한 듯 함.

1. .deb 패키지 파일을 다운로드 받아 압축해제.
2. qemu-user-static 에물레이트 하기 위해 모든 패키지 구성 스크립트 실행

간단한 사용 예제.
우분투 18.04
sudo apt-get install \
  debootstrap \
  qemu-user-static \
;
debootstrap_dir=debootstrap
sudo debootstrap \
  --arch arm64 \
  --foreign \
  bionic \
  "$debootstrap_dir" \
  http://ports.ubuntu.com/ubuntu-ports \
;
sudo mkdir -p "${debootstrap_dir}/usr/bin"
sudo cp "$(which qemu-aarch64-static)" "${debootstrap_dir}/usr/bin"
sudo chroot "$debootstrap_dir" /debootstrap/debootstrap --second-stage
sudo rm -f "$root_filesystem"

리눅스 커널 컴파일 init/main.c 부팅시 메세지 출력

init/main.c

커널 소스 다운로드
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git
cd ubuntu-bionic

# 작업할 커널 소스버전 변경.
git checkout Ubuntu-4.15.0-20.21
fakeroot debian/rules clean
debian/rules updateconfigs
fakeroot debian/rules build-generic
linux_image="$(pwd)/debian/build/build-generic/arch/x86_64/boot/bzImage"

커널 정보 추출 확인.
https://nautiluslee.blogspot.com/2019/01/config.html

패치 적용
diff --git a/init/main.c b/init/main.c
index b8b121c17ff1..542229349efc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -516,6 +516,8 @@ asmlinkage __visible void __init start_kernel(void)
        char *command_line;
        char *after_dashes;

+ pr_info("I'VE Hae Nam Korea Linux Love man!!!");
+
        set_task_stack_end_magic(&init_task);
        smp_setup_processor_id();
        debug_objects_early_init();

빌드
fakeroot debian/rules build-generic

부팅 메시지 출력
I'VE Hae Nam Korea Linux Love man

Kernel: arch/x86/boot/bzImage is ready  (#3)

우분투 커널 .config 환경 설정 부분 확인 및 추출 방법.

우분투 커널 .config 파일 관련

우분투 git 커널 저장소

debian/config 커널 트리 메타 데이터 git 저장소
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/

우분투 18.04 linux-image-4.15.0-36-generici 커널 패키지에 대한 태크 정보는 Ubuntu-4.15.0-36.39.

config 파일 저장소
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/tree/debian.master/config?h=Ubuntu-4.15.0-36.39

config.common.ubuntu, config.common.amd64, config.flavour.generic 병합 linux-image-4.15.0-36-generic 커널 패키지가 나옴.

병합하는 스크립트
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/tree/debian/scripts/misc/kernelconfig?h=Ubuntu-4.15.0-36.39

# Merge configs
# We merge config.common.ubuntu + config.common.<arch> +
# config.flavour.<flavour>

아키텍쳐 별 구성 파일.
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/tree/debian.master/config/annotations?h=Ubuntu-4.15.0-36.39

환경 설정없이 컴파일
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git linux
cd linux
git checkout Ubuntu-4.15.0-36.39
fakeroot debian/rules clean
debian/rules updateconfigs
fakeroot debian/rules build-generic

현재 커널 설정 내용과 차이점 비교.
diff debian/build/build-generic/.config /boot/config-4.15.0-36-generic

.deb 파일 구성
최종 커널 환경 설정 값
/boot/config-4.15.0-36-generic

커널 이미지
/boot/vmlinuz-4.15.0-36-generic

패키지 버전 확인
dpkg -S /boot/config-4.15.0-36-generic

패키지 파일은 다음 내용을 제공 함.
linux-modules-4.15.0-36-generic: /boot/config-4.15.0-36-generic

패키지 정보 목록 확인
https://packages.ubuntu.com/bionic-updates/linux-modules-4.15.0-36-generic

환경 구성 파일 추출
mkdir config
cd config
wget http://mirrors.kernel.org/ubuntu/pool/main/l/linux/linux-modules-4.15.0-36-generic_4.15.0-36.39_amd64.deb
ar x linux-modules-4.15.0-36-generic_4.15.0-36.39_amd64.deb
tar -xvf data.tar.xz
cat ./boot/config-4.15.0-36-generic

debootstrap amd64 전체 이미지 파일 구성 qemu

debootstrap amd64
모든 패키지 다운로드 구성
#!/usr/bin/env bash
# https://askubuntu.com/questions/281763/is-there-any-prebuilt-qemu-ubuntu-image32bit-online/1081171#1081171

set -eux

debootstrap_dir=debootstrap
root_filesystem=debootstrap.ext2.qcow2

sudo apt-get install \
  debootstrap \
  libguestfs-tools \
  qemu-system-x86 \
;

if [ ! -d "$debootstrap_dir" ]; then
  # Create 디렉토리 생성.
  # - linux-image-generic: /boot 사용할 커널 이미지 다운로드
  # - network-manager: 부팅시 네트워크 사용
  sudo debootstrap \
    --include linux-image-generic \
    bionic \
    "$debootstrap_dir" \
    http://archive.ubuntu.com/ubuntu \
  ;
  sudo rm -f "$root_filesystem"
fi

linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"

if [ ! -f "$root_filesystem" ]; then
  # Set root password.
  echo 'root:root' | sudo chroot "$debootstrap_dir"  chpasswd

  # 루투 파일시스템 rw 모드로 마운팅.
  cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF

  # 네트워크 시작.
  # 네트워크 명령어 입력 실패시 :
  #    일시적 실패....
  # https://askubuntu.com/questions/1045278/ubuntu-server-18-04-temporary-failure-in-name-resolution/1080902#1080902
  cat << EOF | sudo tee "$debootstrap_dir/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF
  sudo ln -sf "$debootstrap_dir/etc/systemd/system/dhclient.service" \
    "${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"

  # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
  sudo chmod +r "${linux_image}"

  # debootstrap 디렉토리에 이미지 파일 생성.
  # 1Gb 공간 남겨둔.
  sudo virt-make-fs \
    --format qcow2 \
    --size +1G \
    --type ext2 \
    "$debootstrap_dir" \
    "$root_filesystem" \
  ;
  sudo chmod 666 "$root_filesystem"
fi

qemu-system-x86_64 \
  -append 'console=ttyS0 root=/dev/sda' \
  -drive "file=${root_filesystem},format=qcow2" \
  -enable-kvm \
  -serial mon:stdio \
  -m 2G \
  -kernel "${linux_image}" \
  -device rtl8139,netdev=net0 \
  -netdev user,id=net0 \
;

login: root
pw: root

인터넷 동작 확인
wget그리고 curl기본적으로 설치되지 않기 때문에 다음 명령어로 인터넷 동작 확인
ping 또한 qemu에서 기본적으로 동작 하지 않음.

printf 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n' | nc example.com 80
apt-get update
apt-get install hello
hello

UEFI Cloud image arm64

UEFI Cloud image arm64
sudo apt-get install qemu-efi

자동 스크립트
vi uefi_cloud_image.sh

#!/usr/bin/env bash
set -eux

#sudo apt-get install cloud-image-utils qemu-system-arm qemu-efi

# 이미지 다운로드.
img=ubuntu-18.04-server-cloudimg-arm64.img
if [ ! -f "$img" ]; then
  wget "https://cloud-images.ubuntu.com/releases/18.04/release/${img}"
  qemu-img resize "$img" +60G
fi

# 암호 설정.
user_data=user-data.img
if [ ! -f "$user_data" ]; then
  cat >user-data <<EOF
#cloud-config
password: totoro
chpasswd: { expire: False }
ssh_pwauth: True
EOF
  cloud-localds "$user_data" user-data

  # EFI 사용:
  # https://wiki.ubuntu.com/ARM64/QEMU
  dd if=/dev/zero of=flash0.img bs=1M count=64
  dd if=/usr/share/qemu-efi/QEMU_EFI.fd of=flash0.img conv=notrunc
  dd if=/dev/zero of=flash1.img bs=1M count=64
fi

qemu-system-aarch64 \
  -M virt \
  -cpu cortex-a57 \
  -device rtl8139,netdev=net0 \
  -m 4096 \
  -netdev user,id=net0 \
  -nographic \
  -smp 4 \
  -drive "if=none,file=${img},id=hd0" \
  -device virtio-blk-device,drive=hd0 \
  -drive "file=${user_data},format=raw" \
  -pflash flash0.img \
  -pflash flash1.img \
;

login: ubuntu 
pw:totoro

ubuntu wayland manager qemu kvm 활성화

Unable to init server: Could not connect: Connection refused 

사용자 추가(sudo GUI + terminal)
xhost -si:localuser:root

$ xhost +si:localuser:root

GL에서 GPU 장치 선택

GL에서 GPU 장치 선택

OpenGL 자체가 렌더링 API임.
GLX, WGL, EGL과 같은 윈도우 시스템 바인딩 API는 수 많은 세월에 거쳐 만들어짐.
멀티 GPU 시스템이 찾기 어려웠던 시대...

멀티 GPU API는 제조사 마다 다르지만 MESA 솔루션의 DRI_PRIME를 통해 발전함.

DRI_PRIME란?
초창기의 DRI_PRIME는 2개의 GPU에서 동작 하도록 정의한 환경 변수.
응용 프로그램 호출하기 전에 1로 설정하면 GL 스택이 X서버로 쿼리하고 시스템에 있는 다른 GPU를 사용.

이러한 방법으르로 초기에 발전 함.
- 시스템에 GPU가 3개 이상 있을때?
- x 서버가 없는 시스템일 때?
- 응용 프로그램 개발시 사용할 GPU를 어떻게 선택해 사용할 것인가?

사용자 ID_PATH_TAG가 udev에서 제공 한대로 DRI_PRIME 장치를 나열하여 선택할 수 있다.
EGL의 확장 가능구조 덕분에 EGLDevice 계열의 확장을 통해 해결할 수 있음.

EGLDevice 입력
EGL_EXT_device_base 확장 측면에서 구현된 EGL_EXT_device_enumeration 및 EGL_EXT_device_query.

EGLDevice는 장치고유 속성을 나열해 질문하는 수단 인 EGLDevice의 개념 정의.
또 다른 두 개의 확장 EGL_EXT_device_drm 및 EGL_MESA_device_software은

각각의 하드웨어 DRM 장치 노드 및 소프트웨어와 백업 장치 정의
- 메사로 사용해 GL 구현.

사용 사례
확장 세트를 사용하려면 어떤 장치를 사용할지 명시 적으로 선택한다

그래픽 서버/윈도우 메이지먼트는 전력 소모가 적은 장치로 렌더링한다.
webGL 신뢰할 수 없는 장치로 분류 할 수 있고, 시간 기준으로 GPU 작업을 처리한다.

구현 상태

EGL_EXT_device_base- 구현 모두 EGL_EXT_device_enumeration와EGL_EXT_device_query
EGL_EXT_device_drm
EGL_MESA_device_software
EGL_EXT_platform_device

Cloud image amd64

1. Cloud image amd64
데스크탑 시스템 설치없이 직접 부팅 할 수있는 이미지임.
이게 가능한 이유는 https://help.ubuntu.com/community/CloudInit
여기 사이트에 설명 되어 있음.

즉 init 개념을 -> Cloudint 개념을 추가해 부팅 시퀀서를 만듬.

이미지 생성 스크립트
vi upstream.sh
#!/usr/bin/env bash

sudo apt-get install cloud-image-utils qemu qemu-system qemu-system-x86

# qcow2 형식.
img=ubuntu-18.04-server-cloudimg-amd64.img
if [ ! -f "$img" ]; then
  wget "https://cloud-images.ubuntu.com/releases/18.04/release/${img}"

  # sparse resize: 추가 공간을 사용하지 않고 나중 크기 변경 허용.
  # https://superuser.com/questions/1022019/how-to-increase-size-of-an-ubuntu-cloud-image
  qemu-img resize "$img" +128G
fi

user_data=user-data.img
if [ ! -f "$user_data" ]; then
  # 암호.
  # https://serverfault.com/questions/920117/how-do-i-set-a-password-on-an-ubuntu-cloud-image
  # https://askubuntu.com/questions/507345/how-to-set-a-password-for-ubuntu-cloud-images-ie-not-use-ssh
  cat >user-data <<EOF
#cloud-config
password: totoro
chpasswd: { expire: False }
ssh_pwauth: True
EOF
  cloud-localds "$user_data" user-data
fi

qemu-system-x86_64 \
  -drive "file=${img},format=qcow2" \
  -drive "file=${user_data},format=raw" \
  -device rtl8139,netdev=net0 \
  -enable-kvm \
  -m 2G \
  -netdev user,id=net0 \
  -serial mon:stdio \
  -smp 2 \
  -vga virtio \
;
:wq

QEMU 시작 후 부트 메뉴가 나타나면, 엔터 입력.

부트 메시지
error: no such device: root.

Press any key to continue...

특정 시간이 지나면 자동 부팅 됨.

사용자 이름: ubuntu
암호: totoro

인터넷 동작 확인.

callback test

/*
 * Callback.c - 연결 목록 콜백 구현
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct NODE {
struct NODE *link;
int data;
}Node;

Node **create_sll(const int);
void insert_data(Node **);
void show_list(Node **);
void sort_list(Node **);

int compare_ints(void const *, void const *); /* 프로토타입 함수 */
Node *search_list(Node *, void const *, int(void const *, void const *)); /* 프로토타입 */

int main(void){
int (*compare)(void const *, void const *) = compare_ints;

int value, val2find;
int nodes; /* 노트 카운트 */
Node **rootp; /* 루투 위치 */
Node *desired_node;

puts("\n**Program creates Singly Linked List**");
puts("**And allows users to perform various operations on the"
"list**\n");
puts("User, specify number of nodes in the list, in range 1"
" through some positive no.");
scanf("%d", &nodes);

rootp = create_sll(nodes);

printf("Les's insert %d integers in the list...\n", nodes);
insert_data(rootp);

puts("**Les's show up the list**");
show_list(rootp);

puts("Let's sort the list, in ascending order...");
sort_list(rootp);
puts("Let's show up the list**");
show_list(rootp);

puts("**Let's use Callback() function**");
printf("User, enter an integer you want to see into the "
"Singly Linked List...\n");
scanf("%d", &val2find);

/* 콜밸 함수 호출 */
desired_node = search_list(*rootp, &val2find, compare);

if(desired_node != NULL)
puts("Desired value is found.");
else
puts("Desired value NOT found.");
return 0;
}

Node *search_list(Node *node, void const *value, int compare(void const *, void const *)){
while(node != NULL){
if(compare(&node->data, value) == 0)
break;
node = node->link;
}

return node;
}

int compare_ints(void const *p2nv, void const *p2v){
if(*(int *)p2nv == *(int *)p2v)
return 0;
else
return 1;
}

Node **create_sll(const int nodes){
int i;
Node *current;
static Node *root;
Node **rootp = &root;

root = (Node *)malloc(nodes * sizeof(Node));

if(root == NULL){
puts("Error: Not Enough Memory!");
exit(1);
} else {
current = root;

for(i = 1; i <= nodes; i++){
if(i == nodes) {
current->link = NULL;
} else {
current->link = current + 1;
current++;
}
}
printf("List with %d nodes created successfully!\n", nodes);
puts("");
}
return rootp;
}

void insert_data(Node **linkp){
Node *next = *linkp;
Node *current;

do {
current = next;
scanf("%d", &(current->data));
next = current->link;
}while(current->link != NULL);
puts("");
}

void show_list(Node **linkp){
Node *next = *linkp;
Node *current;

do{
current = next;
printf("%d", current->data);
next = current->link;
}while(current->link != NULL);
puts("\n");
}

void sort_list(Node **linkp){
int temp;
Node *current = *linkp;
Node *next = current->link;

while(current->link != NULL){
while(next != NULL){
if(current->data > next->data){
temp = next->data;
next->data = current->data;
current->data = temp;
}
next = next->link;
}
current = current->link;
next = current->link;
}
}
/*
 * ./callback

**Program creates Singly Linked List**
**And allows users to perform various operations on thelist**

User, specify number of nodes in the list, in range 1 through some positive no.
5
List with 5 nodes created successfully!

Les's insert 5 integers in the list...
32
53
1
08
0556

**Les's show up the list**
325318556

Let's sort the list, in ascending order...
Let's show up the list**
183253556

**Let's use Callback() function**
User, enter an integer you want to see into the Singly Linked List...
53
Desired value is found */