blktrace는 Block I/O Layer 에서 storage (disk, flash 등)로 입출력이 일어나는 과정을 분석해주는 tracing tool 이다.

blktrace가 분석한 내용을 blkparse 가 parsing하여 결과를 눈으로 쉽게 확인할 수 있게 한다.

[그림 1. blktrace architecture]

blktrace 및 blkparse options


blktrace는 여러 옵션을 사용하여 tracing 할 수 있도록 한다. 아래는 일반적인 blktrace 및 blkparse의 사용법이다.

% blktrace -d <dev> -o - | blkparse -i - -o <trace_file>

-d : Use specified device. May also be given last after options

-o : File(s) to send output to
      (위의 사용법에서는  뒤에 '-'가 오는데 이는 stdout 인 텍스트 터미널을 뜻한다.)

-i : Input file containing trace data, or '-' for stdin 
     (위의 사용법에서 blktrace 의 trace data가 stdout으로 지정했으므로, blkparse도 stdin으로 설정한다.)

위의 명령어로 수행하면 <dev>에서의 Block I/O trace결과가 <trace_file>에 저장된다.

이 외에도 많은 옵션들이 있지만, 특별한 경우에 사용되므로 사용해보지 않았다.


iozone를 이용한 blktrace 분석


1. blktrace 를 수행한다.

 blktrace -d /dev/sdb -o - | blkparse -i - -o ./blktrace.sdb.ext4.iozone

 : 현재 dev는 /dev/sbd 이고 분석결과가 저장된 output file은 임의로 blktrace.sdb.ext4.iozone 로 하였다.

2. iozone을 이용하여 mount된 dev에 io를 수행한다.   

 iozone -w -e -s 64k -f ./mnt/iozone.dummy -i 0

 : 64KB 사이즈의 파일(iozone.dummy)을 sequential write pattern으로 write하였다.

  (iozone에 대한 설명은 생략한다.)

3. blktrace 를 종료하고 결과파일을 확인한다.

dev<mjr,mnr>   <cpu>  <seq_num> <time stamp> <pid> <event> <start blk+#of blk>      <process>
 
 8,16           1        1     1.427376394  5529    Q  WS 274432 + 8                [iozone]
  8,16           1        0     1.427383444     0    m   N cfq5529 alloced
  8,16           1        2     1.427384090  5529    G  WS 274432 + 8                [iozone]
  8,16           1        3     1.427385813  5529    P   N [iozone]
  8,16           1        4     1.427386431  5529    I   W 274432 + 8                [iozone]
  8,16           1        0     1.427387153     0    m   N cfq5529 insert_request
  8,16           1        0     1.427387804     0    m   N cfq5529 add_to_rr
  8,16           1        5     1.427390420  5529    Q  WS 274440 + 8                [iozone]
  8,16           1        6     1.427391162  5529    M  WS 274440 + 8                [iozone]
  8,16           1        7     1.427392450  5529    Q  WS 274448 + 8                [iozone]
  8,16           1        8     1.427392667  5529    M  WS 274448 + 8                [iozone]
 ...
  8,16           1       83     1.538002853  5529    U   N [iozone] 1
  8,16           1       84     1.538011856  5529    D   W 274432 + 128              [iozone]
  8,16           1       85     1.591459857     0    C   W 274432 + 128              [0]

결과파일에서 pid=5529 를 가지는 iozone process가 실제로 write 작업을 수행하고 있는 과정을 확인할 수 있다.

실제로 block i/o 동작을 간단히 살펴보자. 

a. seq_num=5 에서 Q event 가 수행된다. Q는 Queue의 약어로, make_request_fn가 수행되어 bio처리가 시작되었음을 나타낸다. 

b. seq_num=6 에서 event 가 수행된다. M은 Merge의 약어로, 앞선 bio request 와 통합되었음(plugged)을 나타낸다. 

c. Q->M 동작이 128 sector (64KB) 까지 반복된다. 이는 현재 iozone이 sequential write를 수행하기 때문에 모든 bio request들이 하나로 통합(merge)됨을 알 수 있다.

d. seq_num=83 에서 event 가 수행된다. U는 unflugged의 약어로, plugged list 내의 request를 I/O scheduler에게 전달했음을 나타낸다. 

e. seq_num=84 에서 D event 가 수행된다. D는 dispatch의 약어로, I/O scheduler가 block device driver에게 수행하라고 요청한 것이다.

f. seq_num=85 에서 event 가 수행된다. C는 complete의 약어로, dispatch된 request의 I/O동작이 완료되었음을 나타낸다.


<event> field 뒤에는 RWBS field로 다음과 같이 정리된다. 

RWBS DESCRIPTION

       This is a small string containing at least one character ('R' for read, 'W'  for  write,  or  'D'  for block discard
       operation), and optionally either  a  'B'  (for  barrier  operations)  or  'S'  (for   synchronous operations).


위 과정을 보면, iozone에서 실제 128KB의 sequential write 요청에 대한 Block I/O 동작을 확인할 수 있다. blktrace는 Block I/O뿐만 아니라 I/O scheduler의 동작까지도 확인할 수 있다. 

아래는 blkparse 결과파일에서 확인할 수 있는 모든 event에 대해 정리한 것이다.


(출처 : http://linux.die.net/man/1/blkparse)


Trace Actions

The following trace actions are recognised:
C -- complete
A previously issued request has been completed. The output will detail the sector and size of that request, as well as the success or failure of it.
D -- issued
A request that previously resided on the block layer queue or in the i/o scheduler has been sent to the driver.
I -- inserted
A request is being sent to the i/o scheduler for addition to the internal queue and later service by the driver. The request is fully formed at this time.
Q -- queued
This notes intent to queue i/o at the given location. No real requests exists yet.
B -- bounced
The data pages attached to this bio are not reachable by the hardware and must be bounced to a lower memory location. This causes a big slowdown in i/o performance, since the data must be copied to/from kernel buffers. Usually this can be fixed with using better hardware -- either a better i/o controller, or a platform with an IOMMU.
M -- back merge
A previously inserted request exists that ends on the boundary of where this i/o begins, so the i/o scheduler can merge them together.
F -- front merge
Same as the back merge, except this i/o ends where a previously inserted requests starts.
M --front or back merge

One of the above

M -- front or back merge
One of the above.
G -- get request
To send any type of request to a block device, a struct request container must be allocated first.
S -- sleep
No available request structures were available, so the issuer has to wait for one to be freed.
P -- plug
When i/o is queued to a previously empty block device queue, Linux will plug the queue in anticipation of future ios being added before this data is needed.
U -- unplug
Some request data already queued in the device, start sending requests to the driver. This may happen automatically if a timeout period has passed (see next entry) or if a number of requests have been added to the queue.
T -- unplug due to timer
If nobody requests the i/o that was queued after plugging the queue, Linux will automatically unplug it after a defined period has passed.
X -- split
On raid or device mapper setups, an incoming i/o may straddle a device or internal zone and needs to be chopped up into smaller pieces for service. This may indicate a performance problem due to a bad setup of that raid/dm device, but may also just be part of normal boundary conditions. dm is notably bad at this and will clone lots of i/o.
A -- remap
For stacked devices, incoming i/o is remapped to device below it in the i/o stack. The remap action details what exactly is being remapped to what.


출처 : http://ji007.tistory.com/archive/20120426

'Embedded Lab > linux, x86' 카테고리의 다른 글

[blktrace 사용법]  (0) 2013.04.08
[blktrace2]  (0) 2013.04.08
[printk 로그 레벨]  (0) 2013.04.08
[환경변수 삭제]  (0) 2013.04.07
[간단한 블록 디바이스 드라이버 모듈(램디스크)]  (0) 2013.04.07
Posted by cyj4369
,

커널 함수에서 사용되는 출력 함수이다.

printf와의 차이는 메시지 기록관리를 위한 로그레벨을 지정할 수 있다는 것이다.

로그레벨                        명령어 의미

  "<0>"     KERN_EMERG         시스템이 동작하지 않는다.

  "<1>"     KERN_ALERT         항상 출력

  "<2>"     KERN_CRIT         치명적인 정보

  "<3>"      KERN_ERR        오류 정보

  "<4>"     KERN_WARNING 경고 정보 

  "<5>"     KERN_NOTICE         정상적인 정보 

  "<6>"     KERN_INFO         시스템 정보 

  "<7>"     KERN_DEBUG        디버깅 정보


위처럼 로그레벨을 지정하는 이유는 kernel source 내에서 원하는 정보만 출력할 수 있게 함이다.


사용법은 다음과 같다


 printk(KERN_ERR"This is KERN_ERR option\n");


다음 명령을 실행해보면 현재의 로그레벨을 확인 할 수 있다.


 $cat /proc/sys/kernel/prink 

      7     4     1     7


[7] : 현재 로그레벨

       이 레벨보다 높은 메시지(숫자가 작은 수)만 출력을 해준다.

[4] : 기본 로그레벨

       printk()함수를 입력하면서 별도로 로그레벨을 입력하지 않을 경우

[1] : 최소 로그레벨

       부여할 수 있는 최소 로그레벨이다.

       이 값이 1이라면 우리가 printk 함수를 입력하면서 0을 부여할 수 없다.

[7] : 부팅시 로그레벨

        부팅시 출력될 레벨을 지정해주는 것이다.


출력되지 않았을 경우 다음과 같은 명령어로 로그버퍼에 기록된 내용을 볼 수 있다. (출력되지 않은 메시지도 볼 수 있음)

dmesg

# cat /proc/kmsg

'Embedded Lab > linux, x86' 카테고리의 다른 글

[blktrace2]  (0) 2013.04.08
[blktrace1]  (0) 2013.04.08
[환경변수 삭제]  (0) 2013.04.07
[간단한 블록 디바이스 드라이버 모듈(램디스크)]  (0) 2013.04.07
[환경변수 삭제]  (0) 2013.03.29
Posted by cyj4369
,

export의 반대는..

unset '환경변수이름'

'Embedded Lab > linux, x86' 카테고리의 다른 글

[blktrace1]  (0) 2013.04.08
[printk 로그 레벨]  (0) 2013.04.08
[간단한 블록 디바이스 드라이버 모듈(램디스크)]  (0) 2013.04.07
[환경변수 삭제]  (0) 2013.03.29
[리눅스 압축명령]  (0) 2013.03.28
Posted by cyj4369
,

My current work involves writing my first Linux block device driver. Going to the web to find a sample, I discovered Jonathan Corbet's Simple Block Driver article with its associated block driver example code. It's a nice succinct implementation of a ramdisk - pretty much the simplest working block device. There's only one problem, though, the article was written in 2003, when kernel 2.6.0 was the new kid on the block. Trying to build it on openSUSE 11.2 with kernel 2.6.31 just produced a slew of compile errors. A bit of research revealed that there were major changes to the kernel block device interface in 2.6.31, so I would have to port the example to get it working.

About a day and a half of poring through the kernel source and the excellent LDD3 (hardcopy) later, I had a running simple block driver for kernel 2.6.31. I've also tested it successfully on SUSE 11 SP1 Beta, which uses kernel 2.6.32. Here's the code, followed by instructions for getting it working.

sbd.c

/*
 * A sample, extra-simple block driver. Updated for kernel 2.6.31.
 *
 * (C) 2003 Eklektix, Inc.
 * (C) 2010 Pat Patterson <pat at superpat dot com>
 * Redistributable under the terms of the GNU GPL.
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/kernel.h> /* printk() */
#include <linux/fs.h>     /* everything... */
#include <linux/errno.h>  /* error codes */
#include <linux/types.h>  /* size_t */
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>

MODULE_LICENSE("Dual BSD/GPL");
static char *Version = "1.4";

static int major_num = 0;
module_param(major_num, int, 0);
static int logical_block_size = 512;
module_param(logical_block_size, int, 0);
static int nsectors = 1024; /* How big the drive is */
module_param(nsectors, int, 0);

/*
 * We can tweak our hardware sector size, but the kernel talks to us
 * in terms of small sectors, always.
 */
#define KERNEL_SECTOR_SIZE 512

/*
 * Our request queue.
 */
static struct request_queue *Queue;

/*
 * The internal representation of our device.
 */
static struct sbd_device {
	unsigned long size;
	spinlock_t lock;
	u8 *data;
	struct gendisk *gd;
} Device;

/*
 * Handle an I/O request.
 */
static void sbd_transfer(struct sbd_device *dev, sector_t sector,
		unsigned long nsect, char *buffer, int write) {
	unsigned long offset = sector * logical_block_size;
	unsigned long nbytes = nsect * logical_block_size;

	if ((offset + nbytes) > dev->size) {
		printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
		return;
	}
	if (write)
		memcpy(dev->data + offset, buffer, nbytes);
	else
		memcpy(buffer, dev->data + offset, nbytes);
}

static void sbd_request(struct request_queue *q) {
	struct request *req;

	req = blk_fetch_request(q);
	while (req != NULL) {
		// blk_fs_request() was removed in 2.6.36 - many thanks to
		// Christian Paro for the heads up and fix...
		//if (!blk_fs_request(req)) {
		if (req == NULL || (req->cmd_type != REQ_TYPE_FS)) {
			printk (KERN_NOTICE "Skip non-CMD request\n");
			__blk_end_request_all(req, -EIO);
			continue;
		}
		sbd_transfer(&Device, blk_rq_pos(req), blk_rq_cur_sectors(req),
				req->buffer, rq_data_dir(req));
		if ( ! __blk_end_request_cur(req, 0) ) {
			req = blk_fetch_request(q);
		}
	}
}

/*
 * The HDIO_GETGEO ioctl is handled in blkdev_ioctl(), which
 * calls this. We need to implement getgeo, since we can't
 * use tools such as fdisk to partition the drive otherwise.
 */
int sbd_getgeo(struct block_device * block_device, struct hd_geometry * geo) {
	long size;

	/* We have no real geometry, of course, so make something up. */
	size = Device.size * (logical_block_size / KERNEL_SECTOR_SIZE);
	geo->cylinders = (size & ~0x3f) >> 6;
	geo->heads = 4;
	geo->sectors = 16;
	geo->start = 0;
	return 0;
}

/*
 * The device operations structure.
 */
static struct block_device_operations sbd_ops = {
		.owner  = THIS_MODULE,
		.getgeo = sbd_getgeo
};

static int __init sbd_init(void) {
	/*
	 * Set up our internal device.
	 */
	Device.size = nsectors * logical_block_size;
	spin_lock_init(&Device.lock);
	Device.data = vmalloc(Device.size);
	if (Device.data == NULL)
		return -ENOMEM;
	/*
	 * Get a request queue.
	 */
	Queue = blk_init_queue(sbd_request, &Device.lock);
	if (Queue == NULL)
		goto out;
	blk_queue_logical_block_size(Queue, logical_block_size);
	/*
	 * Get registered.
	 */
	major_num = register_blkdev(major_num, "sbd");
	if (major_num < 0) {
		printk(KERN_WARNING "sbd: unable to get major number\n");
		goto out;
	}
	/*
	 * And the gendisk structure.
	 */
	Device.gd = alloc_disk(16);
	if (!Device.gd)
		goto out_unregister;
	Device.gd->major = major_num;
	Device.gd->first_minor = 0;
	Device.gd->fops = &sbd_ops;
	Device.gd->private_data = &Device;
	strcpy(Device.gd->disk_name, "sbd0");
	set_capacity(Device.gd, nsectors);
	Device.gd->queue = Queue;
	add_disk(Device.gd);

	return 0;

out_unregister:
	unregister_blkdev(major_num, "sbd");
out:
	vfree(Device.data);
	return -ENOMEM;
}

static void __exit sbd_exit(void)
{
	del_gendisk(Device.gd);
	put_disk(Device.gd);
	unregister_blkdev(major_num, "sbd");
	blk_cleanup_queue(Queue);
	vfree(Device.data);
}

module_init(sbd_init);
module_exit(sbd_exit);

Makefile

obj-m := sbd.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

There are two main areas of change compared with Jonathan's original:

  • sbd_request() uses the blk_fetch_request()blk_rq_pos(),blk_rq_cur_sectors() and __blk_end_request_cur() functions rather thanelv_next_request()req->sectorreq->current_nr_sectors andend_request() respectively. The structure of the loop also changes so we handle each sector from the request individually. One outstanding task for me is to investigate whetherreq->buffer holds all of the data for the entire request, so I can handle it all in one shot, rather than sector-by-sector. My first attempt resulted in the (virtual) machine hanging when I installed the driver, so I clearly need to do some more work in this area!
  • The driver implements the getgeo operation (in sbd_getgeo), rather than ioctl, since blkdev_ioctl now handles HDIO_GETGEO by calling the driver's getgeo function. This is a nice simplification since it moves a copy_to_user call out of each driver and into the kernel.

Before building, ensure you have the kernel source, headers, gcc, make etc - if you've read this far, you likely have all this and/or know how to get it, so I won't spell it all out here. You'll also need to go to the kernel source directory and do the following to prepare your build environment, if you have not already done so:

cd /usr/src/`uname -r`
make oldconfig && make prepare

Now, back in the directory with the sbd source, you can build it:

make -C /lib/modules/`uname -r`/build M=`pwd` modules

You'll see a warning about 'Version' being defined, but not used, but don't worry about that :-). Now we can load the module, partition the ramdisk, make a filesystem, mount it, and create a file:

opensuse:/home/pat/sbd # insmod sbd.ko
opensuse:/home/pat/sbd # fdisk /dev/sbd0
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x5f93978c.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-16, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-16, default 16):
Using default value 16

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
opensuse:/home/pat/sbd # mkfs /dev/sbd0p1
mke2fs 1.41.9 (22-Aug-2009)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
64 inodes, 504 blocks
25 blocks (4.96%) reserved for the super user
First data block=1
Maximum filesystem blocks=524288
1 block group
8192 blocks per group, 8192 fragments per group
64 inodes per group

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 24 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
opensuse:/home/pat/sbd # mount /dev/sbd0p1 /mnt
opensuse:/home/pat/sbd # echo Hi > /mnt/file1
opensuse:/home/pat/sbd # cat /mnt/file1
Hi
opensuse:/home/pat/sbd # ls -l /mnt
total 13
-rw-r--r-- 1 root root     3 2010-04-29 07:04 file1
drwx------ 2 root root 12288 2010-04-29 07:04 lost+found
opensuse:/home/pat/sbd # umount /mnt
opensuse:/home/pat/sbd # rmmod sbd

Hopefully this all works for you, and is as useful for you as it has been for me. Many thanks to Jonathan for the original version and the excellent LDD3. One final piece of housekeeping - although the comment at the top of sbd.c mentions only GPL, the MODULE_LICENSE macro specifies "Dual BSD/GPL". I am interpreting the original code as being under the dual GPL/BSD license and this version is similarly dual licensed.

UPDATE (Feb 5 2011) See the comment by Michele regarding changes to logical_block_size!


출처 : http://blog.superpat.com/2010/05/04/a-simple-block-driver-for-linux-kernel-2-6-31/

'Embedded Lab > linux, x86' 카테고리의 다른 글

[printk 로그 레벨]  (0) 2013.04.08
[환경변수 삭제]  (0) 2013.04.07
[환경변수 삭제]  (0) 2013.03.29
[리눅스 압축명령]  (0) 2013.03.28
[리눅스가 부팅이 안될 때/MBR에 GRUB을 다시 설치하는 방법]  (0) 2013.03.28
Posted by cyj4369
,

[인터뷰]

기타/기타 2013. 4. 4. 21:52

거의 1년간 블로그를 안했네요. 다시 시작하면 하고 싶은 이야기가 여럿 있는데, 오늘은 우선 최근에 이메일로 했던 교수신문과의 인터뷰 내용을 올립니다. 별 내용은 없지만 Enjoy!

———————————

Q. 어렸을 때부터 컴퓨터와 프로그래밍을 좋아했는지요?

아니요. 컴퓨터를 처음 갖게 된것은 1991년이니까 얼리 유저라고 할 수 있지만, 사실 게임을 하는게 주 목적이었고 프로그래밍이나 해킹같은 것은 꿈도 꾸지 않았습니다. 그저 게임하는게 좋았습니다. 고등학교때 하숙하며 친한 대학생 형이 밤새 프로그래밍 하는 모습을 뒤에서 많이 지켜봤습니다. 왠지 모르지만 그 모습이 신나 보였고 그곳에 무언가 있어보였죠. 그래서 대학교때 전공을 컴퓨터로 선택했습니다. 프로그래밍을 처음 배울때는 늦게 시작해서 그랬는지 많이 고생했습니다. 그래도 어설프게나마 내가 만든 창조물이 돌아가는 모습을 보는 건 기뻤습니다. 일종의 중독이라고 생각합니다.

Q. 미국에서 박사학위 취득까지 가장 어려웠던 점은 무엇이었나요? 한국과 미국에서 공부하며 느낀 학술문화의 차이점이 있으신가요?

박사과정 초기에 퀄시험이 있습니다. 학위를 할만한 지식, 자질이 있는가를 테스트하는데 정말로 힘들었습니다. 같이 공부했던 한국 학생들 여러명중 한번에 통과한 분이 없었습니다. 어려움의 가장 큰 이유는 물론 제 자신이 뛰어나게 공부를 잘하지 못했던 것이지만, 사실 한국과 미국의 커리큘럼 차이가 큰 문제점이기도 했습니다. 미국의 컴퓨터과학(Computer Science) 경우 학부생들에게 기초 이론에 초점을 맞추어 교육합니다. 즉 계산 이론(Computational Theory), 알고리즘(Algorithm), 자료 구조(Data Structure) 등의 과목입니다. 한국의 커리큘럼은 기초 과목을 쉽게 쉽게 넘어갑니다. 대신 응용 분야를 많이 교육하고 학교들은 이를 자랑합니다. 예를 들어, 게임 프로그래밍, 실시간 시스템, 네트워크 프로그래밍 등입니다. 저는 이것이 정말 큰 문제라고 생각합니다. 응용 분야를 학교에서 강조하는 이유는 사실 기업과 정부의 보이지 않는 입김 때문입니다. 사회에 나가서 당장 써먹을만한 소위 “인재”를 키우라는 것입니다. 그 결과로 아는 것은 많아 보이는데 정작 기본기가 없는, 영혼 없는 인재들이 대학에서 배출된다는게 문제입니다. 제가 바로 퀄시험에서 여러번 탈락할 수 밖에 없는 영혼없는 인재였기 때문에 잘 압니다.

학부 4학년때 수강한 과목 교수님의 첫 수업시간 이야기가 잊혀지지 않습니다. 그 과목은 앞에서 이야기한 그런 “고급 응용” 과목입니다. 대략 이런 스토리였습니다: “너희들 졸업하고 나서 지금 배우는 과목 X를 써먹을 일은 없을거야. 이 분야는 이제 한물 갔고, 회사들은 Y 방식의 기술을 만들거든. 하지만 나는 X 기술에서 국내 최고였어.” 그 솔직하신 말대로 수업에서 배운것은 아무 쓸모도 없었습니다. 3학점을 환불받고 싶은게 지금 심정입니다.

Q. 박사까지 공부하려는 의지는 직업으로서의 학자를 염두에 둔 게 아니었는지요? 왜 학문으로서의 연구를 떠났는지요? 왜 논문을 쓰지 않으시는지요?

박사과정을 하면서 논문을 제법 많이 썼고, 최고 논문상 후보에 오르기도 했습니다. 졸업을 하고 스타트업 회사에서 일을 시작하면서는 논문을 쓰지 않았습니다. 가장 큰 이유는 스타트업 회사에서 일하면서 논문을 쓸 여유도, 이유도 없다는 점입니다. 박사과정에서는 논문을 쓰는게 당연했습니다. 그 과정도 즐겼고 결과도 좋았습니다. 특별히 논문을 쓰는 과정에서 얻어지는 훈련 – 즉 배경 지식을 습득하고, 아이디어를 생각해낸후 그것을 증명해 단 10장의 종이에 적어내려가는 것 -, 이것은 세상 어디에서도 배울 수 없는 최고의 지적 훈련이라고 생각합니다.

다만 내가 쓴 논문이 얼마나 내 분야에, 넓게 봐서는 사회에 공헌을 하는가 돌아봤을때는 자신있게 Yes라고 말할 수 없었습니다. 2000년 이후 컴퓨터 분야를 선도하는 것은 학계가 아니라 산업계입니다. 빅데이터, 클라우드 모두 구글, 아마존, 페이스북과 같은 회사들에서 처음 아이디어가 나왔고 이를 구체화 시켰습니다. 예전에는 반대의 경우가 많았습니다. 운영체제, 데이터베이스, 암호이론등 핵심 아이디어는 학교들에서 나왔고 이를 처음 구현했던 것도 학교였습니다. 예를 들어 현재의 애플 맥 OS는 카네기 멜론 대학에서 만든 Mach 라는 커널에서 비롯됐습니다. 그래서 예전에는 학교등에서 연구하고 논문 쓰는 것이 실제 공헌을 많이 했습니다.

현재 미국과 한국 많은 학교들의 연구 내용, 논문을 보면 회사들에서 이미 해결한 “죽은 문제”를 붙잡고 아주 작은 부분들만 바꿔보면서, 새로움으로 포장하고 있다고 생각합니다. 세상의 99%는 신경쓰지 않는 작은 문제들을 습관처럼 붙들고 해결하고 있지요. 졸업후 두가지 길의 갈래에 섰을때, 주저없이 좀 더 의미있는 일을 할 수 있는 회사를 선택했습니다. 비록 예전과 같이 10페이지 논문을 매년 몇편씩 생산해 내지는 않지만, 매일 매일 제가 만드는 코드는 전 세계 곳곳에서 사용되고 고쳐집니다. 그게 더 보람이 있습니다.

Q. 학자로서의 길과 개발자로서의 커리어 패스는 많이 다른 것인가요? 산학연 연구가 활성화되고 있는 측면에서, 오히려 현장에서의 경험이 더욱 중요하지 않은가요?

학자로서의 길은 그 종착역이 교수, 국가 연구소 연구원등 제한적인데 반해 개발자의 캐리어 패스는 아주 많습니다. 미국의 경우 회사들도 많고, 연봉등의 대우도 의사등의 몇몇 전문직을 제외하고는 가장 좋은 편입니다. 종종 직업의 안정성을 이유로 연구직을 선호하는 경우가 있는데 제 의견은 다릅니다. 젊어서 두뇌가 획획 돌아가는 사람들이 할 수 있는 영역 (예를 들어 스타트업 회사들)이 있고, 수십년간 닦아온 내공과 지혜를 필요로 하는 영역들 (예를 들어 시스템 아키텍트)이 있습니다. 어떤 회사도 “우리는 개발자가 너무 많다”고 불평하는 곳이 없습니다. 소프트웨어 개발에는 고유한 어려움이 있고 IT산업은 지속적으로 성장하기 떄문에, 전문성을 확보한 SW 인력은 영원히 부족합니다.

최근 미국에서 경험하는 한가지 트렌드는 학교의 고급 두뇌들이 산업계로 유출되는 현상입니다. 예를 들어 하버드 대학교에서 종신 보장(tenure)을 받은 컴퓨터과 교수가 구글로 이직했습니다. 제 논문을 지도했던 교수도 종신 보장을 받자마자 구글로 이직했습니다. 그만큼 현장이 매력적이기 때문입니다. 학교들은 교수를 확보하지 못해 비상입니다. 학교에서 산업계로는 유출되는데, 반대의 경우는 거의 없습니다. 제가 생각하는 한가지 문제는 학교가 산업계와 너무 담을 쌓아놓고 자신만의 프리미엄을 유지하려는 태도입니다. 예를 들어 산업계에서 뛰어난 인재를 학교에서 교수로 채용하는 것은 현재로서는 거의 불가능합니다. 한국에서는 규정상 논문의 정량을 채워야 하는데 산업계 인재는 사소한 논문 많이 쓰는 것에 신경쓰지 않습니다. 이러한 프로세스는 학교라는 우물에 과거형 인재들만 가득한 현상을 낳고 맙니다.

Q. 교육 및 연구의 측면에서, 한국으로 돌아오지 않는 이유는 무엇인가요?

한국에서는 스타트업을 하기 어렵기 때문입니다. 현재 제가 일하는 회사는 클라우드 스타트업입니다. 새로운 분야를 개척하는 일을 하고 있습니다. 연구를 시작할때도 그랬지만 새로운 분야를 개척하는 것이 가장 보람있고 즐겁습니다. 스타트업은 그 자체가 새로운 이론의 실험이기 때문에 논문을 쓰지 않더라도 연구입니다. 이전에 잠시 유명 스타트업에서 일한적이 있는데 그곳에서는 전략적으로 한국 개발자들만 채용했습니다. 왜냐하면 미국 개발자들에 비해 열정과 재능있는 사람들이 한국에 많이 숨어있기 때문입니다. 그런 분들의 경우 기존의 틀을 깨고 새로운 것을 시작하고 싶어하는 성향이 아주 강합니다. 그런 긍정적인 의미의 해커들이 미국에서는 스타트업을 해서, 마이크로소프트, 구글, 페이스북을 만들었습니다. 하지만 삼성등의 대기업이 독점해 큰 것을 더 크게 키우려는 한국 현실에서 그런 사람들을 받아줄 곳이 없습니다. 대기업은 정형화된, 적당히 잘하는 인재를 원하지 판을 깨고 새로운 것을 창조할 수 있는 해커를 원하지 않습니다. 저는 대기업 기준의 인재나 논문을 많이 쓰는 연구원보다는 긍정적인 의미에서의 해커로 남고싶기 때문에 미국에서 일합니다.

Q. 한국은 그야말로 클라우드 유행입니다. 클라우드 컴퓨팅 관련 전문가가 되려는 학생들이 많습니다. 현업에서 느끼는 클라우드 기술 동향과 향후 전망은 어떠한가요?

종종 설명은 화려하지만 몇년 지나고나면 사라지는 일종의 패션과 같은 기술들이 있습니다. 클라우드는 분명히 그런 buzzword 와는 다릅니다. 현재 IT의 큰 두갈래 줄기는 모바일과 클라우드입니다. 모바일 분야에서는 어떻게하면 컴퓨터가 사람과 가장 가까운 곳에서 사람을 도울까를 고민합니다. 구글 글래스가 그 뱡향에서의 새로운 실험입니다. 클라우드는 수십억개의 그런 모바일 디바이스들에게 서비스를 제공하는 보이지않는 백엔드 기술입니다. 과거에는 서버 몇대에 데이터베이스와 웹서버를 돌려서 처리했다면 지금은 수십억개의 디바이스에서 요청하는 정보를 수백만대의 서버들이 서로 통신하며 개인에 맞추어 서비스를 제공합니다. 미래로 갈수록 기존 개념의 데스크탑, 노트북은 사라지고 데이터와 서비스가 모두 보이지 않는 클라우드에서 제공될 것입니다. 그래서 지속적으로 클라우드 전문가에 대한 수요는 증가할 것입니다.

Q. SW개발자의 하루 일과는 어떠한가요? 한국과 미국에서 각각 일해본 경험이 있으신데, 비교해서 설명해주실 수 있는지요?

지금 일하는 회사는 특이하게 전 직원의 60% 정도가 집에서 일합니다. 회사의 본부는 캘리포니아에 있는데 몇달에 한번씩 회사로 출장(!)을 가서 디자인 회의등을 하고 개발, 테스트등의 모든 업무는 집안의 제 오피스에서 합니다. 어떤 직원은 심지어 케이블도 없는 산속 깊은 곳에 살면서 위성 인터넷으로 접속해 일을 합니다. 같이 일한지 3년이 되어가는데 아직 얼굴을 못봤습니다. 그만큼 회사의 분위기가 자유롭습니다. 제 경우에는 낮에는 아이들 학교에 데려다 주거나 같이 놀아주는 시간이 많고 대신 밤에 일을 많이 하는 편입니다. 혹 일이 잘 안되거나 모임이 있을때는 하루 쉬고 골프등으로 여가를 즐깁니다. 저희 회사에는 정해진 휴가 일수가 없습니다. 원한다면 언제든 휴가를 갈 수 있습니다. 즉 언제 일하는지, 어디서 일하는지에 대해 아무도 간섭하거나 하지 않습니다.

자유로운 분위기라고 적은 양의 일을 하는 것은 아닙니다. 스타트업에서 일하며 공유하는 목표가 있기 때문에 누가 시키지 않아도 스스로 일을 많이 합니다. 평균적으로 따지면 하루에 약 10시간 정도는 일을 하는것 같습니다. 관리와 승진이라는 보상체계가 동기를 부여하지 않고, 새로운 기술을 만드는 즐거움, 그리고 스타트업이 성공했을때 얻는 큰 금전적 보상등이 동기를 부여하기 때문에 더 생산적으로 일을 많이 합니다.

Q. 트위터에 SW만으로 성공한 케이스라든지, 1조원 가치의 코딩 이야기 등을 언급하셨습니다. 전통적 개념의 제품이 아닌, SW제품의 특징 혹은 가능성은 무엇이라고 보십나요?

SW제품의 특징은 한 사람이 하나의 산업 전체를 갈아 엎어버릴 정도로 영향력이 있다는 사실입니다. 예를들어, 현재 저희 회사의 CEO가 예전에 성공시켰던 오픈소스 데이터베이스 MySQL의 경우 창업자 혼자 90% 이상을 코딩했다고 합니다. 훗날 1조원 넘는 가격에 회사가 팔렸습니다. 즉 한 사람이 1조원 가치의 코딩을 했다는 이야기 입니다. 한 사람이 소프트웨어에 대해 가지고 있는 고정된 마인드가 회사와 산업 방향을 크게 결정합니다. 스티브잡스의 간결함에 대한 집착이 여전히 애플을 정의하고 있고, 빌게이츠가 추구한 생산성있는 SW는 마이크로소프트가 비지니스 영역을 꽉 잡고 있게끔 했습니다. 구글은 창업자 두 사람이 대학원 기숙사에서 시작했기 때문에 여전히 학교 기숙사 같은 매력적인 개발 문화를 유지하고 있습니다.

종종 한국의 기관, 언론에서 그런 인재를 길러내야 한다는 이야기를 하는데 얼토당토 않은 소리입니다. 그런 소위 IT시대의 영웅들은 길러내는것이 아니라 자유로운 문화속에서 자생하는 것입니다. 기존의 IT, 경제, 사회의 틀을 바꾸어보고 싶은, 일종의 반란을 꿈꾸는 사람들 중에서 툭 튀어 나오는 것 같은 사람들이 바로 그런 인재 입니다. 반란자를 길러낸다는 이야기는 애초에 모순입니다. 미국의 경우 매년 그런 사람들이 툭 툭 튀어 나옵니다. 한국의 경우 SW의 매력이 왜곡돼버려 애초에 큰 꿈을 품는 젊은사람들이 사라지는게 정말 안타깝습니다.

Q. 컴퓨터 관련 전공으로, 미국 유학을 준비하거나 유학 중인 (졸업예정자) 학생들에게 커리어패스의 관점에서 조언을 해준다면?

저는 박사학위 후의 커리어패스가 어찌보면 굳이 박사학위를 필요로 하지 않는 스타트업 업계입니다. 그렇지만 박사학위 6년의 시간이 아깝지는 않습니다. 그 시간동안 컴퓨터과학의 기본을 다시 배웠고, 연구하는 프로세스를 몸에 체득했습니다. 특히 학생시절에는 여유가 많아 SW나 과학 전반에 관련된 다양한 교양 서적들을 읽었던 건 럭셔리한 시간이었다고 생각합니다. 대학원은 충분하 가치있는 투자입니다.

위에서 언급했지만, 커리어패스를 생각할때 너무 직업의 안정성이나 주변의 시선을 생각하지 않았으면 합니다. 그보다는 자신이 가장 즐거운 일, 그리고 조금 위험스럽게 보여도 세상을 바꿀만한 일에 자신을 던지는 사람들이 많았으면 좋겠습니다. 미국의 스타트업 업계의 경우 한 회사가 혹 실패 하더라도 개발자들에겐 실패가 없습니다. 실리콘밸리 자체가 스타트업의 거대한 시스템이기 때문에 어디에든 다음 목표를 추구할 회사들이 존재합니다. 금전적인 보상도 대기업에 비해 부족하지 않습니다. 기회가 닿을때는 자신이 회사를 시작할 수도 있습니다. 아직은 한국 출신으로 실리콘밸리 스타트업에서 일하는 사람들을 많이 만나지 못했습니다. 몇년 후에는 더 많은 후배들을 만나서 신나게 이야기하는 날이 오면 좋겠습니다.



출처 http://sangminpark.wordpress.com

Posted by cyj4369
,

환경변수 삭제


unset

Posted by cyj4369
,

## 리눅스 압축 명령어

* tar 

tar은 은밀히 말하면 압축방식이 아니다. 일종의 묶음 파일로 이해하는 것이 좋을듯 하다.
이 tar과 gzip을 같이 사용하는 경우 tar.gz (또는 tgz)라는 확장자를 사용하게 된다.
tar이 비록 묶음 파일이라 하더라도 여기서는 압축파일의 하나로 이해하고 이를 묶고 푸는
방법에 대해 알아보도록 한다.


- 압축 생성
  # tar cvf temp.tar temp/
    ; temp 디렉터리를 temp.tar 이라는 파일로 묶는다.

     (temp 디렉터리와 그 이하의 모든 파일 및 디렉터리)

 

- 압축 해제
  # tar xvf temp.tar

 

※ 옵션설명
  -c : (create) 압축 파일을 생성한다.
  -x : (extract) 압축 파일을 해제한다.
  -v : 압축파일이 생성(해제)되는 과정을 보여준다.
  -f : 압축파일 또는 Archive 장치를 사용한다.
  -t : 압축파일 내용 확인
  -r : 압축파일 추가
  -z : gzip으로 압축/해제
  -j : bzip2으로 압축/해제

※ tar 명령에서 옵션 앞에 붙는 "-" 기호는 붙여도 되고, 붙이지 않아도 된다.

※ gzip과 같이 압축된 파일의 경우 (tar.gz 또는 tgz) -z 옵션을 사용하여 한번에
   처리할 수 있다.
 

 

* gzip (tar.gz 또는 tgz)
 
앞서 보았던 tar로 묶여진 파일을 다시 압축하는 방법으로 많이 사용되는 압축형태이다.
gzip 명령으로 압축하고 gunzip 명령으로 압축을 해제한다.


- 압축 생성
  
  # gzip temp.tar
  
  위 명령을 사용하면 temp.tar.gz 이라는 파일이 생성된다.

 

- 압축 해제
 
  # gunzip temp.tar.gz
  
  
  # gzip -d temp.tar.gz


 

※ gzip 명령으로 압축을 해제하면, 그 전단계인 tar 묶음 형태로 압축이 풀리게 되므로
   tar 명령으로 다시한번 묶음을 해제해야 한다. 최근에는 이러한 번거로운 과정을
   줄이기 위해 tar 명령에서 tar 묶음 및 gzip 압축까지 모두 해제할 수 있는 옵션(-z)을
   제공한다.
  
  # tar xzvf temp.tar.gz
 

 

* bzip2 (bz2) 

gzip과 같이 최근 많이 사용되는 압축 형태로 tar.bz2 라는 확장자로 다루어진다.
역시 tar 묶음에 다시 압축을 가하는 형태이며, bzip2 전용 명령도 있으며, 
tar에서도 한번에 사용할 수 있는 옵션(-j)이 있다.

- 압축 생성
  # bzip2 -zkv temp.tar

- 압축 해제
  # bunzip2 temp.tar.bz2

※ bzip2 명령으로 압축을 해제하면, tar 명령을 다시 사용해야 하므로, 최근에는 tar에서
   바로 해제하는 경우가 많다.
  
  # tar xjvf temp.tar.bz2
 
* zip 

zip 파일은 Windows에서도 많이 사용되는 압축 형태로, 리눅스에서도 동일하게 사용할 수 있다.

- 압축 생성
  
  # zip -v temp.zip temp/*
   
    ; temp 디렉터리 이하의 모든 파일을 zip으로 압축한다.

- 압축 해제
  
  # unzip temp.zip
 
* compress

확장자 .Z 형태의 압축파일 생성

# compress    [파일명]     : 압축시 

# uncompress  [파일명]    : 해제시  

* zcat 명령어 

zcat -DVv [file...]

zcat 명령은 compress 명령 또는 mkszip 명령으로 압축된 data file을 input으로 취한다.
만약 data file이 command line에 적혀 있지 않는다면 standard input을 읽게 된다.
또한 standard input을 어떤 파일로 적으므로써 zcat에 보낼수 있다.

zcat은 모든 압축된 입력 파일의 압축을 풀어서, standard out에 적는다.
zcat은 cat이 하는 것과 동일한 concatenates을 한다.

압축된 inputfile의 이름은 .z, .gz, bz2로 끝날것을 예상한다.
특정 파일이름이 이런 첨자로 끝나지 않는다면, zcat은 file.z, file.gz, file.bz2로 끝나는
파일을 찾는다. 예를 들어 command line에 abc라는 파일이 적혀있다면,
zcat은 abc.z, abc.gz, abc.bz2를 찾는다. 만약에 이들 중 어느 것도 찾지 못한다면,
zcat은 abc를 확장자 없이 취급한다.

zcat은 다음과 똑같다.

uncompress -c

옵션

-D : compress나 mkszip의 directory option을 사용해서 압축된 파일을 압축해제하라.

-V : zcat의 version을 화면에 나타내라.

-v : 압축된 파일의 각각의 이름을 화면에 나타내라.

Posted by cyj4369
,

여러가지 이유로 MBR이 제거되는 경우가 있는데(저같은 경우는 윈도우와 리눅스를 같이 사용하다 윈도우를 재설치하여 MBR이 제거됨)
다음 단계를 거치면 MBR을 복구할 수 있다.

1단계 :   리눅스 설치 CD 1번(grub를 지원하는 어느  배포판이든 가능(?))을 가지고 복구 모드로 부팅을 한다. (전 우분투 6.10이 설치되어 있었는데 Fedora 6 시디를 사용)
boot: linux rescue

2단계 : 부팅을 한후 복구 모드로 들어가서 다음 명령어를 사용하여 실행한다.
 sh-3.1#: grub

3단계 :grub 실행후 grub shell에서 다음 명령어를 사용하여 실행한다.
grub> root (hd0,2)
Filesystem type is ext2fs, partition type 0x83

위 명령어를 실행하였을 경우 Filesystem ... 라고 나오면 성공한것이고 그렇지 않으면  
Filesystem type unknown, partition type 0x82  또는 Error 23: Error while parsing number 
메시지가 출력된다.

참고 :   위의 명령어중 hd0,2 라는 것이 있는데  이것은  사용자의 파티션에 따라서  모두 다릅니다.  따라서  사용자의 하드디스크의 수및 파티션수에 따라  입력을 하여야 합니다.
저는 하드디스크  하나(hd0)에 윈도우 파티션이 2개 그외 리눅스 파티션을 이용하고 있었습니다. 만약 2개 하드디스크를 사용하고 있는데 두번째 하드디스크에 리눅스를 설치하였다면  hd1 입니다.  하드디스크의 수는 0번부터 시작합니다. 
그리고 2라는 것은 /boot (만약 /boot 파티션을 별도로 잡지 않고 / 파티션에 설치하였을 경우는 / )가   설치되어 있는 파티션 번호입니다.  이것은 /dev/sda3에 설치되어 있었기 때문에 이 번호 또한 0번부터 시작하므로 2가 됩니다.

/dev/sda1 => 윈도우 C  드라이브
/dev/sda2  => 윈도우 D 드라이브
/dev/sda3 => 리눅스 /boot 
/dev/sda4 => 리눅스 /
/dev/sda5 => 리눅스 swap

4단계: MBR에 GRUB를 설치한다.(대부분의 경우 첫번째 하드디스크입니다.)
grub> setup (hd0)
Checking if "/boot/grub/stage1" exists ... no
Checking if "/grub/stage1" exists ... yes
Checing if "/grub/stage2" exists ... yes
Checking if "/grub/e2fs_stage1_5" exists ... yes
Running "embed /grub/e2fs_stage1_5 )hd0)" .. . 15 sectors are embedded.
Running "install /grub/stage1 (hd0) (hd0)1+15 p (hd0,2)/grub/stage2 /grub/grub.conf"... succeeded.
Done.

5단계: grub shell에서 빠져나오고 리부팅을 시켜준다.
grub>quit
sh-3.1# reboot ( 또는 ctrl + alt + del  키를 누른다.)

혹시라도 리부팅후 바로 부팅매니저가 나오지 않고 grub shell로 빠질경우 3,4단계를 다시한번 해준다. 그리고 리부팅하면 정상적으로 될 것이다.

참고사항 #1

grub 상태에서 윈도우로 부팅하려면 (C 드라이브에 윈도가 깔려있다고 할 경우) 다음 명령어를 실행하면 된다.

grub>root  (hd0,0)
grub>chainloader +1
grub>boot


grub 상태에서 리눅스를 부팅하려면

grub>root(hd0,2)  //여기서 2는 리눅스가 설치된 파티션을 말한다.

grub>kernel  /커널파일이름 ro root=/dev/sda3 ro  quiet  splash (Ubuntu)

grub>kernel  /커널파일이름 ro root=/dev/sda3 ro  rhgb  quiet  (RedHat 계열)

grub>boot

=>  커널파일이름 :  vmlinuz-2.6.x 와 같은 형식으로 되어 있다.  (/boot/grub/menu.lst 참고)
 
참고 사항 #2
윈도우와 리눅스를 같이 사용하다 리눅스를 삭제한후에 혹시라도 부팅할때 부트 매니저  lilo, grub 등이 남아 있을 경우는 아래 방법으로
하드 디스크(hard disk)의 MBR 영역을 초기화 해주면 된다.


첫번째 방법 : 응급복구 디스크를 이용하여(fdsik  파일포함) 도스(DOS)로 부팅해서 명령 프롬프트(command prompt)에서   fdisk /mbr  실행

두번째 방법 : 윈도xp CD로 부팅해서 복구 모드(recovery mode)로 들어간 후 명령 프롬프트(command prompt)에서   fixmbr 실행

'Embedded Lab > linux, x86' 카테고리의 다른 글

[환경변수 삭제]  (0) 2013.03.29
[리눅스 압축명령]  (0) 2013.03.28
[우분투에서 GRUB메뉴가 안보일 때]  (0) 2013.03.28
[에뮬레이터와 시뮬레이터의 차이]  (0) 2013.03.24
[어셈블리와 어셈블러]  (0) 2013.03.17
Posted by cyj4369
,

1.
/etc/default/grub 을 편집한다.


2.
GRUB_HIDDEN_TIMEOUT=0 를 주석처리한다.
(GRUB_TIMEOUT=10이라는 것은 10초후에 자동으로 부팅된다는것...)


3.
update-grub 을 때리고 재부팅.

Posted by cyj4369
,

게임 중에 시뮬레이션 게임들이 있죠.
그 시뮬레이션 게임들은 실제 상황을 시뮬레이션 해서 만드는 것입니다.
즉, 실제와 완전히 똑같을 필요까지는 없고 시뮬레이션하는 대상이 지니는 주요 특성만을 
재현해주면 되는 것입니다.
비행 시뮬레이션 이라면 하늘을 나는 것처럼 3D표현으로 화면에 보여주고
하늘을 나는 것처럼 조작할 수 있게 해주면 되는 것이죠.
물론 실험용 시뮬레이션이라면 바람이나 기후에 의한 영향이라던지
기체의 상태에 의한 영향 같이 더 자세한 특성들을 재현해줘야 하는 것이지만
그렇다고 해서 모든 것(화면 모습의 텍스쳐를 실제 현실처럼 자세하게 해줘야 한다거나 하는...)을
재현할 필요까지는 없습니다. 
심지어는 어떠한 시뮬레이션의 경우는 단순히 그 상황에 대한 관측 수치만 제공하는 경우도 있습니다.

그에 반해 에뮬레이터는 재현고자 하는 대상을 완벽하게 재현하는 것이 목표입니다.
어떠한 PDA를 에뮬레이션 하려고 한다면 PDA에 사용된 cpu가 처리할 수 있는 명령어들을
그대로 처리할 수 있는 가상의 cpu를 구현해야 하고 PDA에 사용된 디스플레이와 같은
해상도에서 PDA와 동일한 성능으로 PDA에서 돌아가는 프로그램을 사용할 수 있어야 합니다.
간단히 말하자면 에뮬레이터는 어떠한 하드웨어를 소프트웨어 적으로 재구현하는 것이죠.
(유사하게 하드웨어 -> 하드웨어는 짝퉁(카피) (중국의 짝퉁 자동차나 짝퉁 mp3같은... ) 
소프트웨어 -> 소프트웨어는 클론( 네이트온을 대신하는 Jateon 같은... )
소프트웨어 -> 하드웨어는 생각이 안나는군요. (이러는 경우가 있기는 하던가요;;)
이라고 할 수 있겠습니다. )

그리고 그 설명에서는

"시뮬레이터는 하드웨어도 포함할 수도 있지만
에뮬레이터는 소프트웨어적으로만 구현하는 것을 의미한다."

라고 이해하시면 될거 같습니다.
저 차이는 두가지를 완벽하게 구분하는데 사용하기는 힘든 특성이죠.

즉, 시뮬레이션은 소프트웨어적, 하드웨어적, 혹은 소프트웨어+하드웨어 등을 동시에 사용하여
어떠한 상황에 대한 자세한 데이터를 수집하거나 보여주는 것이 목적이고,

에뮬레이션은 어떠한 하드웨어를 소프트웨어적으로 구현하여 대상 하드웨어를 사용하는 것과
동일하게 사용하는 것이 목적이라고 할 수 있겠습니다.

============================================================

에뮬레이션은 진실값으로 대체 하는 거고, 시뮬레이션은 모델링 한 적절한 값으로 대체 하는 겁니다.
어떤 시스템을 모델링 한다는 것은 그 시스템과 100% 일치되지는 않지만 주요 특징을 살리는 결과물을 
만들어 내는 것입니다.따라서 "xxx 를 시뮬레이션 해보자" 하는 것은 xxx 의 주요 특징을 모델링 하고 (주로 수식으로)
거기에 입력을 가한 후 출력을 보는 것입니다.
에뮬레이션은 100% 동일해야 합니다. 현실에서 어려운 경우가 많죠.

과거에는 프로그래밍 할 때 에뮬레이터나 시뮬레이터를 사용했습니다.
가령 8086 이나 Z80 을 개발한다면 해당 에뮬레이터를 구입해서 (노트북 만하게 생겼습니다.)
개발중인 보드의 cpu 대신에 에뮬레이터 소켓을 꼽습니다.
그러면 이제 부터 에뮬레이터가 해당 cpu 를 대신 합니다.
에뮬레이터를 작업 pc 에 연결해서 작업합니다.
cpu 내부 실행되는 상황파악은 물론, 각 핀들을 물리적으로 컨트롤합니다. cpu 와 완전 동일한 거죠.

에뮬레이터가 비싸서 어려움이 있다면 시뮬레이터를 구입합니다. 이것은 소프트웨어의 일종입니다.
작업 pc 에서 소프트웨어를 구동하고 target cpu 를 프로그램적으로 하나 만들어 내서 
내가 작성한 코드를 실행해 주죠. 물리적인(전기적인) 동작은 할 수 없고,
프로그램의 논리관계만 검증합니다.

지금 주류가 된 ARM mcu 도 초기에는(2000년대 초반 ???) arm 에서 판매하는 500만원짜리 에뮬레이터를 
가지고 작업했습니다. 지금은 그거 없어도 무관한 것 같은데요....ㅎㅎㅎ.

Posted by cyj4369
,