반응형



/*                                                                                                                                                                 

 *     clock_gettime

 * gcc -Wall -o now now.c -lrt [-D_LOCAL_TIME]

 */

#include <stdio.h>

#include <stdlib.h>

#include <time.h>


#define BUFSIZE     64


/*

    1. 현재 시간을 얻어 온다. clock_gettime / gettimeofday

    2. tm으로 변환해 정보를 출력한다. localtime_r / gmtime_r

    3. 문자열로 변환해 출력한다. asctime_r

*/


int main(void)

{

    struct timespec ts;

    struct tm tm;

    struct tm *ret_tm;


    char buf1[BUFSIZE] = { 0 };

    char *ret_asc;

    int ret;



    /* get current time (struct timespec format) */

    ret = clock_gettime (CLOCK_REALTIME, &ts);

    if (ret < 0)

    {

        perror ("clock_gettime");

        return (EXIT_FAILURE);

    }


    /* change it to 'struct tm' format */

#ifdef _LOCAL_TIME

    ret_tm = localtime_r (&ts.tv_sec, &tm);

#else

    ret_tm = gmtime_r (&ts.tv_sec, &tm);

#endif

    if (ret_tm == NULL)

    {

#ifdef _LOCAL_TIME

        perror ("localtime_r");

#else

        perror ("gmtime_r");

#endif

        return (EXIT_FAILURE);

    }


    printf ("mon: %d day: %d, %d:%d:%d\n",

      tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);


    /* make time string */

    ret_asc = asctime_r (&tm, buf1);

    if (ret_asc == NULL)

    {

        perror ("ret_asc");

        return (EXIT_FAILURE);

    }


    printf ("%s\n", buf1);



    return (EXIT_SUCCESS);

}

반응형
반응형

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하여 터미널에서 확인 할 수 있습니다.















반응형
반응형

ARM Processor 7개의 Mode


  • ARM Processor Modes of Operation


  ARM 프로세서에는 7개의 동작 모드가 있습니다. 동작 모드는 프로세서가 어떠한 권한을 가지고 어떠한 일을 처리하고 있는지 나타내는 Processor의 동작 상태를 말합니다. 각각의 7개의 모드는 따로 SP(Stack Point)를 갖고 있습니다. (User와 System은 같은 Stack을 사용, 6개의 Stack이 존재합니다.)

  각각의 모드는 아래의 표와 같습니다.

Mode

Description

CPSR M[4:0]

User

User Task나 Application을 수항 할때의 동작모드로 모든 동작모드 중 유일하게 비특권 모드이다. User Mode는 메모리, I/O장치와 같은 시스템 자원을 사용하는데 제한을 두어 사용자의 실수를 방지한다. 다른 모드(SVC)로 이동하기 위한 방법으로는 소프트웨어 인터럽트를 발생시킨다.

10000b 

 FIQ(Fast IRQ)

 2개의 인터럽트 소스 중 아주 빠르게 인터럽트를 처리할 수 있도록 구성된 모드이다. 빠른 처를 위해서 Exception Vector에서도 최하단에 존재하고 별도의 레지스터를 소유한다.

10001b 

IRQ(Interrupt Request)

 일반적으로 사용되는 인터럽트로 외부 장치에서 요청되는 하드웨어적인 IRQ의 발생에 의해 ARM Core는 IRQ모드로 전환하고 인터럽트를 처리한다.

10010b 

SVC(Superviser)

 대부분의 시스템 자원을 자유롭게 관리할 수 있는 동작모드로 주로 커널이나 디바이스 드라이버를 처리할 때(System Call) 동작되는 모드이다.

Reset 신호 입력 시 및 SWI가 발생하면 SVC Mode로 전환된다.

10011b 

Abort

 메모리에서 명령을 읽거나 데이터를 읽거나 쓸때 오류가 발생할 때 Abort Mode로 전환하여 오류를 처리한다. 커널등의 패닉시 Abort Mode로 전환되어 스택 내용이 전달됨을 알 수 있다.

10111b 

Undefined

 명령어를 읽어 실행하고자 하나 읽어온 명령이 디코더에 정의되어 있지 않은 명령인 경우 발생되는 오류를 처리하는 모드이다.

11011b 

System

 User Mode와 동일한 Register를 사용하고 동일한 용도로 사용된다.
User Mode와의 차이점은 특권을 갖고 있다는 것이다. (ex : OS Kernel)

11111b 



  위 표에 표시된 우측의 5bit 데이터는 CPSR이라는 Status Register 내에 저장된 데이터입니다. CPSR은 현재 Mode의 Status를 저장하고 있는데, 그중 우측 0~4bit인 총 5bit는 각 모드의 정보를 담고 있습니다. 32bit 중 나머지 bit는 N, Z, C, V로 컨디션 코드 및 기타 정보로 사용됩니다.

  인터럽트나 에러 또는 프로그래머에 의하여 모드가 변경될 수 있습니다. Exception에 의하여 모드가 변경되기에, 각 모드의 특징에 대해 알아야만 합니다.

 Abort, FIQ, IRQ 이외의 System, User, SVC Mode가 상호 모드 전환 간의 명확한 정의가 필요합니다.
System과 User는 같은 Stack을 사용하여 거의 Mode간의 차이가 없으나, User Mode에서는 Device등의 자원을 사용하는데 제한이 주어집니다. SVC Mode는 처음 Reset되었을 때 접근하는 Mode로 시스템 자원을 자유롭게 관리가 가능하며 별도의 Stack을 이용합니다.

User Mode는 OS상에 올라가는 Application의 수행 시,
OS는 기본적으로 System Mode이며,
OS나 Application이 시스템 자원(I/O등의 장치)을 사용할때에는 SVC Mode로 전환 후 사용됩니다.

  이때, SVC Mode로 전환되어 시스템 자원을 사용할 권한을 얻는 것을 OS에서는 System Call이라 말합니다. OS에서 Application에 필요한 메모리 공간과 OS의 실행에 따른 메모리 공간을 분리시켜 관리합니다. Application에서 접근 권한이 없는 시스템 자원에 접근하게 허용하기 위해 운영체제는 프로세서가 제공하는 Mode 전환을 System Call Function으로 정의하여 개발자에게 제공합니다.


  ARM Core의 default Mode는 SVC Mode 입니다. SVC에서 출발하여 boot up시에 ARM Core에 대한 모든 권한을 행사할 수 있어야 하기 때문입니다. U-Boot 등의 부트로더 등의서 ARM Core 부팅 및 리셋 시 SVC 모드로 Start.S 등의 어셈블리어 코드가 실행됨을 알 수 있습니다.

 

반응형

+ Recent posts