Setup > Terminal  메뉴에서


coding[receive]:KS5601

coding[transmit]KS5601:

locale:korean

CodePage:949



* 시스템 리소스의 표현

- 시스템 리소스를 파일로 표현 및 제공하는 것을 의미

- 시스템에 있는 H/W는 물론, 논리적인 시스템 리소스 전반을 파일로 표현

- /proc, /dev, /sys 내에 디바이스 파일이나 프로세스와 관련된 파일, 시스템 리소스를 표현하는 파일 위치

- /dev/sda 파일은 하드디스크 추상화 파일


* 추상화된 파일의 역할

- Application 을 위한 인터페이스 도구

- 리눅스는 사용자 공간과 커널 공간이 가상주소를 기반으로 분리된 시스템 구조

- 이는 Application 이나 커널은 서로 직접적인 접근이 불가능

- Application 이 커널의 리소스를 사용하기 위해서는 S/W 인터럽트인 system call 로 커널의 작업 수행을 요청 하는 구조를 제공


###  udev 란 ?


* 탄생배경

- /dev 밑에 디바이스 파일 노드를 만드는 데 어려움

- RedHat 9 버전인 경우 /dev/에는 18,000 개의 디바이스 노드 파일 존재

- 이후에 생성될 가능성이 있는 모든 디바이스에 대한 모든 노드 파일을 미리 생성


*udev란

- A Userspace Implementation of devfs 의 약자

- 실제로 있는 디바이스에 대한 파일 노드 생성을 사용자 공간에서 자동화하여 처리하도록 구성

- /dev 디렉토리에 장치 노드 파일을 만들거나 제거하는 작업을 동적으로 수행

- 안드로이드에서는 시스템이 부팅될 때 두 개의 데몬이 동작

- udev 와 uevent

- uevent 데몬은 특정 디바이스가 hotplug 되는 경우 커널 영역에서는 모듈과 같은 형태의 device driver 가 로딩되며, 

이 때 해당 디바이스에 대한 정보가 uevent 로 udev 데몬에 전달하며 디바이스 노드 생성시 사용되도록 /sys 디렉토리

내부에 대항 디바이스에 대한 uevent 파일을 생성

- udev 데몬은 수신된 uevent 데이터와 /sys/class/device_name/uevent 파일을 비교하여 /dev 디렉토리 아래에 디바이스

노드 생성 여부를 결정 및 수행


### udev 의 특징


* hotplug

- udev 는 hotplug 서브시스템의 일부로 장치가 시스템에 추가되거나 제거되면 hotplug가 udev를 호출

- udev 는 hotplug 이벤트를 받아 sysfs 에서 필요한 정보를 얻어 /dev 아래에 장치 파일 생성


- 리눅스 부팅 시 init 의 실행 시 /sbin/init 프로세스가 /etc/inittab 로딩 후 각 스크립트 등을 실행

- 이 때 sysfs 를 /sys 로 마운트하여 udev 데몬이 동작

- udev 데몬이 실행 된 후 시스템에서 디바이스 노드 생성

- 실제 디바이스가 detect 되면 sysfs 에 등록되고 해당 디바이스는 사용자 공간에서 /sys에 등록

- udev 데몬으로 netlink socket 을 이용하여 새로운 디바이스가 생성되었다는 메시지를 전송

- udev 데몬은 /sys의 디바이스 내용 (Major, Minor 번호 및 생성할 디바이스 파일의 이름 등) 을

이용해서 /dev 에 디바이스 노드를 생성


### udeventd


* Android 에서의 디바이스 관리 방법

- udev 및 uevent 에 대한 내용은 거의 동일

- 시스템 특성상 이를 변형하여 사용

- Froyo 버전 까지 init 프로세스에 의해서 전반적인 시스템 메니지먼트를 이룸

- Gingerbrad 버전부터는 init 프로세스에서 처리하던 디바이스의 관리를 udeventd 데몬으로 분리




./system/core/init/init.c

 

int main(int argc, char **argv)

{

    ....

    

    if (!strcmp(basename(argv[0]), "ueventd"))

        return ueventd_main(argc, argv);

    ....


}

- init 프로세스의 main 함수는 시작 부분에 ueventd_main 함수를 호출하여 ueventd 데몬 실행

- ueventd 데몬이나 udevd 데몬은 시스템이 초기화되는 시점에 동작하며 /dev 디렉토리 아래에 디바이스 파일을 동적으로 생성


* ueventd 데몬의 동작 구조




ueventd.%hardware%.rc

Nexus Sdml /ueventd.herring.rc 내용

 


/dev/pvrsrvkm            0666    system    system

/dev/uwibro               0660    system    system

/dev/swmxctl             0660    system    system

/dev/video0               0660    system    camera

/dev/video1               0660    system    camera

/dev/video2               0660    system    camera

/dev/s3c-jpg             0660    system    camera

/dev/s3c-mem           0660    system    system

/dev/s3c-mfc            0660     media      media


/dev/modem_ctl          0660     radio       radio

/dev/modem_fmt          0660     radio       radio

/dev/modem_rfs          0660     radio       radio

/dev/s3c2410_serial3   0660     radio       radio

/dev/block/mtdblcok5  0660     radio       radio

/dev/mtd/mtd5ro         0660     radio       radio

/dev/mtd/mtd5            0660     radio       radio


# for Sensor HAL

/dev/akm 8973            0660    system    system

/dev/accelerometer     0660    system    system


# for GPS

/dev/s3c2410_serial1    0600     gps        gps 



- ueventd 데몬은 위 내용 대로 디바이스 파일 생성

- 시스템 부팅 과정에서 기본적으로 /dev 로 마운트하여 사용하는 tmpfs의 내용 이외에 ueventd 데몬에 의해서 관리 될 시스템 디바이스

파일을 의미




./system/core/init/ueventd.c

 


int ueventd_main(int argc, char **argv)

{

    struct pollfd ufd;

    int nr;

    char tmp[32];


    umask(000);



    signal(SIGCHLD, SIG_IGN);


    open_devnull_stdio();

    klog_init();

    

    INFO("starting ueventd\n");


    /* Respect hardware passed in through the kernel cmd line, Here we will look

    * for androidboot.hardware param in kernel cmdline, and save its value in

    * hardware[]. */

    import_kernel_cmdline(0, import_kernel_nv);

    get_hardware_name(hardware, &revision);


    ueventd_parse_config_file("/ueventd.rc");


    snprintf(tmp, sizeof(tmp),"/ueventd.%s.rc", hardware);

    ueventd_parse_config_file(tmp);


    device_init();


    ufd.events = POLLIN;

    ufd.fd = get_device_fd();


    while(1) {

        ufd.revents = 0;

        nr = poll(&ufd, 1, -1);

        if (nr <= 0)

             continue;

        if (ufd.revents == POLLIN)

               handle_device_fd();

    }

}




- 위는 ueventd 데몬의 메인 함수

- ueventd.rc 파일이나 ueventd.%hardware%.rc 파일의 내용을 읽어 해당 내용을 초기화

- device_init() 함수를 호출하여 sysfs 의 내용을 토대로한 /dev 디렉토리 업데이트를 처리하는 coldboot 수행



 

./system/core/init/devices.c



 void device_init(void)

{

    suseconds_t t0, t1;

    struct stat info;

    int fd;

#ifdev HAVE_SELINUX

    struct selinux_opt seopts[] = {

        { SELABEL_OPT_PATH, "/file_contexts" }

    };


    if(is_selinux_enabled() > 0)

       sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

#endif

    /* is 64K enough? udev uses 16MB! */

    device_fd = uevent_open_socket(64*1024, true);

    if(device_fd < 0)

        return;

    

    fcntl(device_fd, F_SETFD, FD_CLOEXEC);

    fcntl(device_fd, F_SETFD, O_NONBLOCK);


    if (stat(coldboot_done, &info) < 0) {

        t0 = get_usecs();

         coldboot("/sys/class");

         coldboot("/sys/block");

         coldboot("/sys/devices");

        t1 = get_usecs();

        fd = open(coldboot_done, O_WRONLY|O_CREAT, 0000);

        close(fd);

        //log_event_print("coldboot%ld uS\n", ((long)(t1 -t0)));

        ERROR("coldboot %ld uS\n", ((long)(t1 -t0)));

    } else {

        //log_event_print("skipping coldboot, already done\n")

        ERROR("skipping coldboot, already done\n");

    }

}



- 위는 device_init() 함수

- coldboot는 내부적으로 do_coldboot를 호출



 

./system/core/init/devices.c


static void do_coldboot(DIR *d)

{

    struct dirent*de;

    int dfd, fd;


    dfd = dirfd(d);


    fd = openat(dfd, "uevent", O_WRONLY);

    if(fd >=0) {

        write(fd, "add\n", 4);

        close(fd);

        handle_device_fd();

    }

    while((de = readdir(d))) {

        DIR *d2;


        if(de ->d_type != DT_DIR || de->d_name[0] =='.')

            continue;


        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);

        if(fd < 0)

            continue;


        f2 = fdopendir(fd);

        if(d2 == 0)

            close(fd);

        else {

            do_coldboot(d2);

            closedir(d2);

         }

    }


- 위는 do_coldboot() 의 내용

- ueventd 데몬은 이오ㅔ에도 커널 2.6에서 지원하는 hotplug 기능을 지원

- hotplug 기능은 커널의 uevent 발생을 실시간 모니터링하며 새로 업데이트된 sysfs 의 내용 (/sys)을 이용하여 디바이스 파일을 생성

- ueventd_main 함수에서 while 루프로 처리하는 부분이 커널에서 발생하는 uevent  를 모니터링 하는 부분이며 처리해야 이벤트 발생 시

   handle_device_fd() 호출




./system/core/init/devices.c

 

 

#define UEVENT_MSG_LEN 1024

void handle_device_fd()

{

    char msg[UEVENT_MSG_LEN+2];

    int n;

    while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {

        if(n >= UEVENT_MSG_LEN) /* overflow -- discard */

            continue;


        msg[n] = '\0';

        msg[n+1] = '\0';


        struct uevent uevent;

        parse_event(msg, &uevent);

       

        handle_device_event(&uevent);

        handle_firmware_event(&uevent);

     }

}




- handle_device_event(&uevent), handle_firmware_event(&uevent) 함수 호출



./system/core/init/devices.c

 


static void handle_device_event(struct uevent *uevent)

{

    if (!strcmp(uevent->action,"add"))

        fixup_sys_perms(uevent->path);


    if (!strncmp(uevent->subsystem, "block",5)) {

        handle_block_device_event(uevent);

    } else if (!strncmp(uevent->subsystem, "platform", 8)) {

        handle_platform_device_event(uevent);

    } else {

        handle_generic_device_event(uevent);

    }

}

 



- handle_device_event() 함수는 각각 action 에 대해서 수행 (add, remove, link)

- add 인 경우 make_device(devpath, path, block, major, minor); 호출하여 mknod 수행



./system/core/init/devices.c 

 

static void handle_firmware_event(struct uevent *uevent)

{

    pid_t pid;

    int ret;

    

    if(strcmp(uevent->subsystem, "firmware"))

        return;


    if(strcmp(uevent->action, "add"))

        return;


    /* we fork, to avoid making large memory allocations in init proper */

    pid = fork();

    if (!pid) {

         process_firmware_event(uevent);

         exit(EXIT_SUCCESS);

    }

}



- handle_firmware_event() 함수는 firmware event 처리







출처 : http://hoonycream.tistory.com/entry/udev

'System Programming > Linux Kernel' 카테고리의 다른 글

라이브러리 로딩 ld.so.conf  (0) 2017.01.17
커널 타이머  (0) 2016.06.08
[Linux] ticket spin lock  (0) 2016.05.17
spin_lock, spin_lock_irq, spin_lock_irqsave  (2) 2016.05.17


linux 부팅 시 프로그램이 실행되도록 간단하게 하기



/etc/rc.d/rc.local



/etc/rc.d/rc.local 파을을 열어 제일 뒤쪽에 부팅시 실행시킬 명령어 및 프로그램 등을 추가 입력해 주면 부팅 시 rc.local 스크립트가 실행될 때

같이 실행 되게 됩니다. (터미널에 넣는 명령어를 넣으면 됩니다.)

'System Programming > Tips' 카테고리의 다른 글

현재시간 얻어오기  (0) 2016.10.04
teraterm 한글 깨짐 및 설정  (0) 2016.09.21
리눅스 압축 / 압축 해제 (zip, tar, tar.gz, tar.bz2)  (0) 2016.09.02
u-boot 분석  (0) 2016.07.11
임베디드 보드 포팅 순서  (0) 2016.07.06

리눅스 압축 / 압축 해제


Zip


    • 압축

$ zip -r [압축파일명.zip] [압축할 파일/디렉토리]

    • 압축 해제

$ unzip [압축파일명.zip]









Tar


    • 압축

$ tar cf [압축파일명.tar] [압축할 파일/디렉토리]

    • 압축 해제

$ tar xf [압축파일명.tar]








Tar.gz



    • 압축

$ tar zcf [압축파일명.tar.gz] [압축할 파일/디렉토리]

    • 압축 해제

$ tar xfz [압축파일명.tar.gz]








Tar.bz2




    • 압축

$ tar jcf [압축파일명.tar.bz2] [압축할 파일/디렉토리]

    • 압축 해제

$ tar xfj [압축파일명.tar.bz2]











Tar.xz



이중으로 압축을 풀어야 합니다.

  • 압축

$ tar cf [압축할 파일명.tar] [압축할 파일/디렉토리]

$ xz [압축할 파일명.tar]
  • 압축 해제(.xz 압축 해제 -> tar 압축 해제)

$ xz -d [압축파일명.tar.xz] 또는 unxz [압축파일명.tar.xz]

$ tar -xf [압축파일명.tar]









※ tar 명령시 -v 옵션을 추가하여 주시면 압축 과정에 대한 목록을 print하여 터미널에서 확인 할 수 있습니다.















+ Recent posts