리눅스/커널2014. 4. 8. 15:10

dentry cache hash table size 지정은,

fs/dcache.c에서 alloc_large_system_hash를 통해서 된다. 그전에 dhash_entries는 kernel cmdline에서 지정하여 원하는 값을 패스 할 수 있다.

2965static void __init dcache_init(void)
2966{
2967        int loop;
2968
2969        /* 
2970         * A constructor could be added for stable state like the lists,
2971         * but it is probably not worth it because of the cache nature
2972         * of the dcache. 
2973         */
2974        dentry_cache = KMEM_CACHE(dentry,
2975                SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
2976
2977        /* Hash may have been set up in dcache_init_early */
2978        if (!hashdist)
2979                return;
2980
2981        dentry_hashtable =
2982                alloc_large_system_hash("Dentry cache",
2983                                        sizeof(struct hlist_bl_head),
2984                                        dhash_entries,
2985                                        13,
2986                                        0,
2987                                        &d_hash_shift,
2988                                        &d_hash_mask,
2989                                        0);
2990
2991        for (loop = 0; loop < (1 << d_hash_shift); loop++)
2992                INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
2993}


그리고 만약 dhash_entries값이 0이면(전역비초기화 변수 이므로 0으로 되어 bss영역에 있을 것이다) 5395라인 하위로 타고 들어가, nr_kernel_pages에 기반을 둔 2의 배수를 설정하고 기타 log2작업(아 이건 나중에 보자...)을 통해 hash table size를 출력한다.

5381void *__init alloc_large_system_hash(const char *tablename,
5382                                     unsigned long bucketsize,
5383                                     unsigned long numentries,
5384                                     int scale,
5385                                     int flags,
5386                                     unsigned int *_hash_shift,
5387                                     unsigned int *_hash_mask,
5388                                     unsigned long limit)
5389{
5390        unsigned long long max = limit;
5391        unsigned long log2qty, size;
5392        void *table = NULL;
5393
5394        /* allow the kernel cmdline to have a say */
5395        if (!numentries) {
5396                /* round applicable memory size up to nearest megabyte */
5397                numentries = nr_kernel_pages;
5398                numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
5399                numentries >>= 20 - PAGE_SHIFT;
5400                numentries <<= 20 - PAGE_SHIFT;
5401
5402                /* limit to 1 bucket per 2^scale bytes of low memory */
5403                if (scale > PAGE_SHIFT)
5404                        numentries >>= (scale - PAGE_SHIFT);
5405                else
5406                        numentries <<= (PAGE_SHIFT - scale);
5407
5408                /* Make sure we've got at least a 0-order allocation.. */
5409                if (unlikely(flags & HASH_SMALL)) {
5410                        /* Makes no sense without HASH_EARLY */
5411                        WARN_ON(!(flags & HASH_EARLY));
5412                        if (!(numentries >> *_hash_shift)) {
5413                                numentries = 1UL << *_hash_shift;
5414                                BUG_ON(!numentries);
5415                        }
5416                } else if (unlikely((numentries * bucketsize) < PAGE_SIZE))
5417                        numentries = PAGE_SIZE / bucketsize;
5418        }
5419        numentries = roundup_pow_of_two(numentries);
5420
5421        /* limit allocation size to 1/16 total memory by default */
5422        if (max == 0) {
5423                max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
5424                do_div(max, bucketsize);
5425        }
5426
5427        if (numentries > max)
5428                numentries = max;
5429
5430        log2qty = ilog2(numentries);
5431
5432        do {
5433                size = bucketsize << log2qty;
5434                if (flags & HASH_EARLY)
5435                        table = alloc_bootmem_nopanic(size);
5436                else if (hashdist)
5437                        table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
5438                else {
5439                        /*
5440                         * If bucketsize is not a power-of-two, we may free
5441                         * some pages at the end of hash table which
5442                         * alloc_pages_exact() automatically does
5443                         */
5444                        if (get_order(size) < MAX_ORDER) {
5445                                table = alloc_pages_exact(size, GFP_ATOMIC);
5446                                kmemleak_alloc(table, size, 1, GFP_ATOMIC);
5447                        }
5448                }
5449        } while (!table && size > PAGE_SIZE && --log2qty);
5450
5451        if (!table)
5452                panic("Failed to allocate %s hash table\n", tablename);
5453
5454        printk(KERN_INFO "%s hash table entries: %ld (order: %d, %lu bytes)\n",
5455               tablename,
5456               (1UL << log2qty),
5457               ilog2(size) - PAGE_SHIFT,
5458               size);
5459
5460        if (_hash_shift)
5461                *_hash_shift = log2qty;
5462        if (_hash_mask)
5463                *_hash_mask = (1 << log2qty) - 1;
5464
5465        return table;
5466}


'리눅스 > 커널' 카테고리의 다른 글

커널 디버깅 방법  (0) 2014.09.19
syslog LOCAL7  (0) 2014.08.28
Memory 정보 출력되는 곳  (0) 2014.04.07
driver 초기화 시에 쓰이는 module_init  (0) 2014.04.04
Machine 이름 바꾸기  (0) 2014.04.03
Posted by code cat
리눅스/커널2014. 4. 7. 19:22

arch/arm/mm/init.c : mem_init(void)


 586        unsigned long reserved_pages, free_pages;
 587        struct memblock_region *reg;
 /*
 633         * Since our memory may not be contiguous, calculate the
 634         * real number of pages we have in this system
 635         */
 636        printk(KERN_INFO "Memory:");
 637        num_physpages = 0;
 638        for_each_memblock(memory, reg) {
 639                unsigned long pages = memblock_region_memory_end_pfn(reg) -
 640                        memblock_region_memory_base_pfn(reg);
 641                num_physpages += pages;
 642                printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
 643        }
 644        printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
 645
 646        printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
 647                nr_free_pages() << (PAGE_SHIFT-10),
 648                free_pages << (PAGE_SHIFT-10),
 649                reserved_pages << (PAGE_SHIFT-10),
 650                totalhigh_pages << (PAGE_SHIFT-10));

include/linux/memblock.h

 150#define for_each_memblock(memblock_type, region)                                        \
 151        for (region = memblock.memblock_type.regions;                           \
 152             region < (memblock.memblock_type.regions + memblock.memblock_type.cnt);    \
 153             region++)
 154

include/linux/memblock.h

 123/**
 124 * memblock_region_memory_end_pfn - Return the end_pfn this region
 125 * @reg: memblock_region structure
 126 */
 127static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
 128{
 129        return PFN_DOWN(reg->base + reg->size);
 130}

include/linux/memblock.h

 132/**
 133 * memblock_region_reserved_base_pfn - Return the lowest pfn intersecting with the reserved region
 134 * @reg: memblock_region structure
 135 */
 136static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
 137{
 138        return PFN_DOWN(reg->base);
 139}


include/linux/memblock.h

  37struct memblock {
  38        phys_addr_t current_limit;
  39        phys_addr_t memory_size;        /* Updated by memblock_analyze() */
  40        struct memblock_type memory;
  41        struct memblock_type reserved;
  42};

meminfo 라는 구조체에 nr_banks 와 membank라는 구조체가 멤버로 있다.  이들은 부팅 과정에서 이미 arm_add_memory라는 함수를 통해서 bank에 대한 start 및 size가 정해졌있다.(
early_init_dt_add_memory()나 parse_tag_mem32()등의 함수를 통해서 세팅된다(확인필요)

  29struct membank {
  30        phys_addr_t start;
  31        phys_addr_t size;
  32        unsigned int highmem;
  33};
  34
  35struct meminfo {
  36        int nr_banks;
  37        struct membank bank[NR_BANKS];
  38};

그리고 arch/arm/mm/init.c:find_limits()라는 함수를 통해서, 각 메모리 뱅크를 돌면서 (참고로 이건 3.1.10소스다. 최신은 좀 틀리다)

 135static void __init find_limits(unsigned long *min, unsigned long *max_low,
 136        unsigned long *max_high)
 137{
 138        struct meminfo *mi = &meminfo;
 139        int i;
 140
 141        *min = -1UL;
 142        *max_low = *max_high = 0;
 143
 144        for_each_bank (i, mi) {
 145                struct membank *bank = &mi->bank[i];
 146                unsigned long start, end;
 147
 148                start = bank_pfn_start(bank);
 149                end = bank_pfn_end(bank);
 150
 151                if (*min > start)
 152                        *min = start;
 153                if (*max_high < end)
 154                        *max_high = end;
 155                if (bank->highmem)
 156                        continue;
 157                if (*max_low < end)
 158                        *max_low = end;
 159        }
 160}

밑의 매크로를 통해서 페이지프레임넘버를 가져온다.  

  45#define bank_pfn_start(bank)    __phys_to_pfn((bank)->start)
  46#define bank_pfn_end(bank)      __phys_to_pfn((bank)->start + (bank)->size)
 139#define __phys_to_pfn(paddr)    ((unsigned long)((paddr) >> PAGE_SHIFT))

가져온 pfn을 start, end에 assign하고 전달받은 min, max_low, max_high를 그에 맞게 설정해 준다.  

그 후, bootmem_init()에서 arm_bootmem_init(min, max_low)를 통해 bootmem bitmap page 할당, bootmem allocator 초기화, lowmem 해재, lowmem memblock reservation 등을 한다.

위의 할당된 bootmem 은 나중에 init/main.c 에서 mem_init()를 호출하면,

 453static void __init mm_init(void)
 454{
 455        /*
 456         * page_cgroup requires countinous pages as memmap
 457         * and it's bigger than MAX_ORDER unless SPARSEMEM.
 458         */
 459        page_cgroup_init_flatmem();
 460        mem_init();
 461        kmem_cache_init();
 462        percpu_init_late();
 463        pgtable_cache_init();
 464        vmalloc_init();
 465}

mem_init()에서 bootmem에 할당되었던 메모리를 해제한다.
 600 totalram_pages += free_all_bootmem();

mm/bootmem.c

 250unsigned long __init free_all_bootmem(void)
 251{
 252        unsigned long total_pages = 0;
 253        bootmem_data_t *bdata;
 254
 255        list_for_each_entry(bdata, &bdata_list, list)
 256                total_pages += free_all_bootmem_core(bdata);
 257
 258        return total_pages;
 259}

자 그러면 이제 우리가 원하던 부분이다.

 610        reserved_pages = free_pages = 0;
 611
 612        for_each_bank(i, &meminfo) {
 613                struct membank *bank = &meminfo.bank[i];
 614                unsigned int pfn1, pfn2;
 615                struct page *page, *end;
 616
 617                pfn1 = bank_pfn_start(bank);
 618                pfn2 = bank_pfn_end(bank);
 619
 620                page = pfn_to_page(pfn1);
 621                end  = pfn_to_page(pfn2 - 1) + 1;
 622
 623                do {
 624                        if (PageReserved(page))
 625                                reserved_pages++;
 626                        else if (!page_count(page))
 627                                free_pages++;
 628                        page++;
 629                } while (page < end);
 630        }
 631
 632        /*
 633         * Since our memory may not be contiguous, calculate the
 634         * real number of pages we have in this system
 635         */
 636        printk(KERN_INFO "Memory:");
 637        num_physpages = 0;
 638        for_each_memblock(memory, reg) {
 639                unsigned long pages = memblock_region_memory_end_pfn(reg) -
 640                        memblock_region_memory_base_pfn(reg);
 641                num_physpages += pages;
 642                printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
 643        }
 644        printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
 645
 646        printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
 647                nr_free_pages() << (PAGE_SHIFT-10),
 648                free_pages << (PAGE_SHIFT-10),
 649                reserved_pages << (PAGE_SHIFT-10),
 650                totalhigh_pages << (PAGE_SHIFT-10));
 651
 652#define MLK(b, t) b, t, ((t) - (b)) >> 10
 653#define MLM(b, t) b, t, ((t) - (b)) >> 20
 654#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
 655
 656        printk(KERN_NOTICE "Virtual kernel memory layout:\n"
 657                        "    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 658#ifdef CONFIG_HAVE_TCM
 659                        "    DTCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 660                        "    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 661#endif
 662                        "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 663#ifdef CONFIG_MMU
 664                        "    DMA     : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 665#endif
 666                        "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 667                        "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 668#ifdef CONFIG_HIGHMEM
 669                        "    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 670#endif
 671                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 672                        "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
 673                        "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
 674                        "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
 675                        "       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",

meminfo의 nr_bank숫자 만큼 루핑을 하면서, bank의 start주소와 end주소의 pfn을 가져와, 각각 page, end에 저장시키고, page에서부터 end까지 안에서 루핑하면서, page가 reserved일 경우, reserved_pages++ 하고, !page_count(page)일 경우 free_pages++하고, 마지막으로 page를 increment시킨다.

 for_each_memblock(memory, reg) 는 
 150#define for_each_memblock(memblock_type, region)                                        \
 151        for (region = memblock.memblock_type.regions;                           \
 152             region < (memblock.memblock_type.regions + memblock.memblock_type.cnt);    \
 153             region++)

memblock_type의 memory안의 memblock_region의 regions을 돌면서(memory의 cnt숫자만큼), 

  26struct memblock_region {
  27        phys_addr_t base;
  28        phys_addr_t size;
  29};
  30
  31struct memblock_type {
  32        unsigned long cnt;      /* number of regions */
  33        unsigned long max;      /* size of the allocated array */
  34        struct memblock_region *regions;
  35};
  36
  37struct memblock {
  38        phys_addr_t current_limit;
  39        phys_addr_t memory_size;        /* Updated by memblock_analyze() */
  40        struct memblock_type memory;
  41        struct memblock_type reserved;
  42};

pages에 region의 base + size의 PFN 값에서 base의 PFN값을 뺀 값을 설정한다.

 639                unsigned long pages = memblock_region_memory_end_pfn(reg) -
 640                        memblock_region_memory_base_pfn(reg);

그리고 이렇게 얻어진 pages를 num_phypages에 증가시켜준다.

그러면 드디오 이 num_phypages >> (20 - PAGE_SHIFT)가
Memory: = xxx MB total

에 나오는 xxx가 된다. 

'리눅스 > 커널' 카테고리의 다른 글

syslog LOCAL7  (0) 2014.08.28
Dentry cache hash table 사이즈  (0) 2014.04.08
driver 초기화 시에 쓰이는 module_init  (0) 2014.04.04
Machine 이름 바꾸기  (0) 2014.04.03
Machine 이름 알아내기  (0) 2014.04.03
Posted by code cat
리눅스/커널2014. 4. 4. 09:13

driver초기화 시에 흔히 불리는 module_init(x)는 include/linux/init.h에

#define module_init(x)    __initcall(x);

로 정의되어 있다.  여기서 x는 kernel 부팅 타임이나 모듈 삽입시에 불리는 함수명이 된다.

built in 모듈일 경우, do_initcalls()에서 불릴 것이고,

module 일 경우, module insertion에 불린다.

'리눅스 > 커널' 카테고리의 다른 글

Dentry cache hash table 사이즈  (0) 2014.04.08
Memory 정보 출력되는 곳  (0) 2014.04.07
Machine 이름 바꾸기  (0) 2014.04.03
Machine 이름 알아내기  (0) 2014.04.03
early_param에 대해  (0) 2014.03.31
Posted by code cat
리눅스/커널2014. 4. 3. 13:39

MACH_TYPE_XXX 와 machine 이름을 overwrite하기 위해서는 아래 매크로를 활용하면 된다.

linux/arch/arm/include/asm/mach/arch.h

  79 * Set of macros to define architecture features.  This is built into
  80 * a table by the linker.
  81 */
  82#define MACHINE_START(_type,_name)                      \
  83static const struct machine_desc __mach_desc_##_type    \
  84 __used                                                 \
  85 __attribute__((__section__(".arch.info.init"))) = {    \
  86        .nr             = MACH_TYPE_##_type,            \
  87        .name           = _name,
  88
  89#define MACHINE_END                             \
  90};


'리눅스 > 커널' 카테고리의 다른 글

Memory 정보 출력되는 곳  (0) 2014.04.07
driver 초기화 시에 쓰이는 module_init  (0) 2014.04.04
Machine 이름 알아내기  (0) 2014.04.03
early_param에 대해  (0) 2014.03.31
/dev/tty 와 /dev/console의 차이점  (0) 2014.02.05
Posted by code cat
리눅스/커널2014. 4. 3. 09:30

start_kernel()-->setup_arch()-->setup_machine_tags()

arch/arm/kernel/setup.c에서setup_arch()함수 내에서 머신이름을 설정한다.

machine_arch_type은 include/generated/mach-types.h에서 정의되어 있는데 이는 gen-mach-types 툴을 이용해서 생성된다.
예)
define MACH_TYPE_CODECAT             1

ifdef CONFIG_CODECAT
define machine_arch_type                   MACH_TYPE_CODECAT

machine_arch_type은 setup_machine_tags의 인자로 넘어가고, setup_machine_tags()내의
for_each_machine_desc는 __arch_info_begin 에서 __arch_info_end 를 순환하면서 machine_desc구조체의 nr(architecture number를 인자로 받아온 machine_arch_type과 비교하여 같은 경우, archiecture name을 찍어준다.

'리눅스 > 커널' 카테고리의 다른 글

driver 초기화 시에 쓰이는 module_init  (0) 2014.04.04
Machine 이름 바꾸기  (0) 2014.04.03
early_param에 대해  (0) 2014.03.31
/dev/tty 와 /dev/console의 차이점  (0) 2014.02.05
FrameBuffer size 구하기  (0) 2013.12.11
Posted by code cat
리눅스/커널2014. 3. 31. 10:14

early_param("HI_MEM", HI_MEM_Init) 

  --> __setup_param(str, fn, fn, 1) 으로 정의되어 있는데 이를 자세히 보면,

static const char __setup_str_##unique_id[] __initcost \
__aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
  __used __section(.init.setup)
  __attribute__((aligned((sizeof(long))))) \
  = { __setup_str_##unique_id, fn, early }


long 사이즈로 align된 .init.setp섹션에 obs_kernel_param 구조체 형태의 __setup_##unique_id 안에 { __setup_str_##unique_id, fn, early } 형태로 초기화 시킨다. 


obs_kernel_param 구조체는 

const char *str
int (*setup_func)(char *);
int early;

로 구성되어 있다.

이렇게 설정된 early_param의 내용은 init/main.c에서 parse_early_options() --> parse_args("early options", cmdline, NULL, 0, do_early_param) --> parse_one()안에서
return handle_unknown에서 do_early_param이 실행된다.

do_early_param을 실행시킬 때, 그동안 쌓인 obs_kernel_param 리스트(?)들을 순회하면서 실행 시킨다.(섹션에 구조체가 리스트로 들어가기 보다는 각각의 구조체가 엔트리로 들어가는 거 같은데 좀 더 확인이 필요하다.)


__setup_start[] 와 __setup_end[]는 include/asm-generic/vmlinux.lds.h 에서 다음과 같이 정의되어 있다.


#define INIT_SETUP(initsetup_align) \ . = ALIGN(initsetup_align); \ VMLINUX_SYMBOL(__setup_start) = .; \ *(.init.setup) \ VMLINUX_SYMBOL(__setup_end) = .;

또한 INIT_SETUP은 arch/arm/kernel/vmlinux.lds.S에서 16byte(?)으로 align되어 있다.

.init.data : { #ifndef CONFIG_XIP_KERNEL INIT_DATA #endif INIT_SETUP(16) INIT_CALLS CON_INITCALL SECURITY_INITCALL INIT_RAM_FS }


좀 더 자세히 봐야 하는데, 결국 맨 위, "HI_MEM"이라는 parameter에 대한 처리를 HI_MEM_init에서 처리할 수 있게 된다.


'리눅스 > 커널' 카테고리의 다른 글

Machine 이름 바꾸기  (0) 2014.04.03
Machine 이름 알아내기  (0) 2014.04.03
/dev/tty 와 /dev/console의 차이점  (0) 2014.02.05
FrameBuffer size 구하기  (0) 2013.12.11
[커널] FB 문서  (0) 2013.12.09
Posted by code cat
리눅스2014. 3. 14. 08:44


--sysroot=dir
Use dir as the logical root directory for headers and libraries. For example, if the compiler normally searches for headers in /usr/include and libraries in /usr/lib, it instead searches dir/usr/include and dir/usr/lib.

If you use both this option and the -isysroot option, then the --sysroot option applies to libraries, but the -isysroot option applies to header files.

The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker does not support this option, the header file aspect of --sysroot still works, but the library aspect does not. 


sysroot 는 컴파일 시에 필요한 header/lib 들을 찾는 경로에 대한 베이스 경로를 지정해 줄 수 있다.

여러가지 용도로 사용할 수 있겠으나, 다음과 같은 경우에 우선 쓸 수 있다.

1. gdb 로 디버깅 시, 타깃머신(gdbserver가 동작중)의 라이브러리들이 소스머신(gdb 동작중)의 라이브러리들과 매칭이 되지 않을 때.

2. toolchain이 소스와 제공(android경우)되어 그 toolchain을 써야 하나, bionic libc에서 지원하지 않는 라이브러리 함수를 어플리케이션이 사용해야 할 때.


위의 노란 부분은 gcc에서 sysroot 사용법에 대한 설명이다.  --sysroot=dir을 설정하면, 컴파일러께서는 dir/usr/include, dir/usr/lib 등으로 찾으신다.

Posted by code cat
$ screen -X -S [session # you want to kill] quit


Posted by code cat
리눅스/커널2014. 2. 5. 11:44

출처:http://chaoxifer-univ.blogspot.kr/2010/10/devtty-devconsole.html


/dev/tty 와 /dev/console의 차이점


There is a subtle difference between the console and the terminal. In a windowed environment, a tty terminal is associated with each shell session; in other words, each command line window such as an xterm is a separate terminal. Redirection to /dev/tty sends output to the active window. The console, on the other hand, is the screen. It is the monitor in general. Most windowing programs provide a special switch to the shell windows that will link /dev/console to the window instead of writing output directly on the screen. In any event, output can be redirected to these devices quite easily.



출처:http://unix.stackexchange.com/questions/60641/linux-difference-between-dev-console-dev-tty-and-dev-tty0


From the documentation:

/dev/tty        Current TTY device
/dev/console    System console
/dev/tty0       Current virtual console

In the good old days /dev/console was System Administrator console. And TTYs were users' serial devices attached to a server. Now /dev/console and /dev/tty0 represent current display and usually are the same. You can override it for example by adding console=ttyS0 to grub.conf. After that your /dev/tty0 is a monitor and /dev/console is /dev/ttyS0.

An exercise to show the difference between /dev/tty and /dev/tty0:

Switch to the 2nd console by pressing Ctrl+Alt+F2. Login as root. Type sleep 5; echo tty0 > /dev/tty0. Press Enter and switch to the 3rd console by pressing Alt+F3. Now switch back to the 2nd console by pressing Alt+F2. Type sleep 5; echo tty > /dev/tty, press Enter and switch to the 3rd console.

You can see that tty is the console where process starts, and tty0 is a always current console.




  • /dev/console is a virtual set of devices which can be set as a parameter at boot time. It might be redirected to a serial device or a virtual console and by default points to /dev/tty0. When multiple console= options are passed to the kernel, the console output will go to more than one device.

  • /dev/tty0 is the current virtual console

  • /dev/tty[1-x] is one of the virtual consoles you switch to with control-alt-F1 and so on.

  • /dev/tty is the console used by the process querying it. Unlike the other devices, you do not need root privileges to write to it. Note also that processes like the ones launched by cron and similar batch processes have no usable /dev/tty, as they aren't associated with any. These processes have a ? in the TTY column of ps -ef output.


'리눅스 > 커널' 카테고리의 다른 글

Machine 이름 알아내기  (0) 2014.04.03
early_param에 대해  (0) 2014.03.31
FrameBuffer size 구하기  (0) 2013.12.11
[커널] FB 문서  (0) 2013.12.09
[안드로이드][커널]Unknown symbol _GLOBAL_OFFSET_TABLE_  (0) 2013.08.09
Posted by code cat

출처: gnu doc for Makefile

 

makefile에서 다른 makefile을 include하고자 할 때는 다음과 같이 한다.

include filename

 

위와 같이 하면, 현재 makefile을 읽는 걸 중단하고, 상기의 filename에 대한 읽기를 진행한다. 포함된 file에 대한 읽기가 끝나면 다시 현재 makefile에 대해 진행한다. 

만약 상기 파일이 /로 시작하지 않거나 현재 디렉터리에 존재하지 않다면 다음과 같은 순서로 찾는다.

 

1. '-I' 혹은 '--include_dir'로 정의된 디렉터리

2. prefix/include('/usr/local/include') '/usr/gnu/include', '/usr/local/include', '/usr/include' 순서로 찾는다.

 

만약 위와 같이 해도 못 찾는다고 해서, 곧바로 에러를 내지는 않는다.(경고 메세지는 나온다.)  우선 현재 makefile에 대한 모든 진행을 맞추고, make는 현재 out-of-date 혹은 아직 존재하지 않는 파일에 대해 진행을 시도한다.  여기서도 만약 실패한다면, 에러가 난다.

 

만약 이런 에러를 피해, 있으면 좋구 없으면 에러내지 말라 라고 하고 싶다면, '-include'를 사용하라.

 

한개 이상의 makefile을 포함하고자 할 때는 다음과 같은 형식으로도 가능하다.

include foo *.mk $(bar)

 

보통 언제 include를 쓰면 좋으냐면,

1. 여러 directory에 makefile들이 존재하고, 공용 variable에 대한 사용을 하고자 할 때

2. 소스 파일로부터의 dependencies를 자동으로 생성코자 할 때.

 

할 때 사용하면 좋다.

 

Posted by code cat