Flash 메모리의 경우 sector 단위로 erase가 가능하며 Erase 된 섹터는 모든 bit가 1이라는 값을 가지게 된다. Flash 메모리에 write 하는 작업은 각 bit별 값을 1 to 0으로 바꾸는 작업으로 반대로 0 to1로 바꾸는 write는 불가능하다. 즉 한번 0이된 bit를 1로 바꾸기 위한 유일한 방법은 해당 bit가 포함된 sector 전체를 erase하는 방법밖에 없다.
flash 메모리에서 각각의 bit는 (일반적으로)한개의 cell에 저장이 되는데 이 cell에 전하를 모두 잃으면 1(charge loss), 전하가 쌓이면(charge gain) 0으로 해석된다. 즉 flash erase는 해당 sector에 전하를 모두 비우는 과정이 된다.
때때로 flash에 저장된 값이 0 to 1 혹은 1 to 0으로 값이 변하는 오류가 발생하기도 하는데 이와 같은 bit flipping이 발생하는 이유가 flash memory 자체의 문제인지 SW의 오류로 발생하는 문제인지를 판단하기 어려운 경우가 많다.
먼저, 특정 bit의 값이 0 to1로 값이 변경되었다면 이는 아래와 같은 이유로 flash device의 문제일 가능성이 매우 높은다.
1. SW적으로 특정 bit만 0 to1로 변경할 수 없다. 앞서 설명한데로 이를 위해서는 해당 sector를 모두 지운 후 해당 bit만 1이되도록 다시 해당 sector 전체를 다시 write를 해야 하는데, 일부러 이렇게 SW를 작성할 이유가 없고, 이러한 버그가 생기기도 거의 불가능하기 때문이다.
2. 해당 bit 정보를 저장하는 flash cell에 전류 leakage가 발생하여 전하가 방전(charge loss)되면, 값이 0 to1로 바뀔 수 있다. 먼저 flash에 0을 write할 때(Charge Gain) 전하가 충분히 주입되지 못하여 전하량이 0과 1의 경계부분에 있다가 시간이 지나면서 발생하는 미세한 방전으로 0 to 1로 값이 바뀔 수 있으며, 이와 같은 방전은 일반적으로 시간이 지남에 따라 자연스레 발생하며 cell 특성에 따라 특정 cell이 다른 cell보다 더 빠르게 방전 되기도 한다. 또한 X-ray등으로 냉납등을 조사하는 공정이 있다면, X-ray조사로 인하여 방전이 더 빠르게 발생하기도 한다.
만일 bit값이 1 --> 0 (charge gain)으로 변경되었다면 이 경우는 좀 더 골치 아픈 경우다. SW적으로 erase없이 1 --> 0으로 해당 bit값 만 바꿀 수 있으므로 0 --> 1로 바뀌는 경우보다는 SW 버그일 가능성이 조금 더 크다고 할 수 있겠다. HW적으로도 전하 loss가 아닌 전하 충전이 발생하여야 가능한 현상인데, 전하는 자연적으로는 방전되지 충전되지는 않는다. (물론 손상된 장치에서 특정 cell이 충전되지 않는다고 보증할 수는 없겠지만 )
참고 사이트
http://j102.net/lecture/3595
앞서서 한 cell에 한 bit가 저장된다고 했는데, 데이터 용량을 늘리기 위해 한 cell에 여러 bit를 저장하는 MirrorBit기술이나 MBC(Multi-Bit Cell) 기술등이 적용되고 있다. 이는 NAND flash에서의 MLC 기술과 유사한 것으로 이해된다.
NAND flash에서는 device특성상 불가피하게 발생하는 bit값 변경을 막기 위해서 ECC를 사용한 값 보정 기능이 오래전부터 사용되고 있으나 NOR에서는 최근에서야 ECC기능이 포함되고 있다. 특히 MLC 기술을 사용하는 NOR에 ECC 적용이 활발하게 이루어지고 있다
2011년 5월 21일 토요일
2010년 10월 1일 금요일
UART로 연결된 두 보드에서 PPP 프로토콜 사용하여 통신하기.
일반적으로 PPP은 dial-up connection을 위해서 사용되는 프로토콜로, 가가호호 인터넷 연결을 위한 ADSL이 도입되기 이전인 8-90년대에 가정에서 모뎀과 전화를 사용하여 인터넷에 연결하기 위해서 많이 사용되던 프로토콜이다.
그만큼 오래되고 내용도 자못 복잡하여 해당 기술의 역사와 내용을 완전히 이해하기 쉽지 않지만 (항상 그러하듯) 실제로 사용하기 위해서 모든 것을 알 필요는 없다.
일단 서버와 클라이언트상에 PPP연결은 아래와 같이 이루어진다.
여기서 서버는 인터넷 제공업체의 컴퓨터, 클라이언트는 가정집의 컴퓨터라고 생각하면 된다.
모뎀을 외장 모뎀이라고 가정하면, 서버-모뎀 혹은 모뎀-클라이언트는 시리얼 포트(COM포트)를 통하여 연결되어 있을 것이고, 시리얼 포트는 내부적으로 레벨 쉬프터를 거쳐 UART 장치에 연결될 것이다. 즉 아래와 같을 것이란 얘기.
먼거리의 서버와 클라이언트를 연결하기 위하여 중간에 여러가지 장치를 거치지만 결국은 서버의 UART 장치와 클라이언트의 UART 장치간의 통신을 위한 프로토콜 되겠다. 뭐가? PPP가.
(참조:
UART는 3.3V를 사용하는데 컴퓨터 외부의 외장모뎀으로 데이터 전송시 데이터가 확실히 전달되도록 12V로 전압을 높여준다. 바로 레벨 쉬프터는 이때문에 필요하다. 이렇게 12V로 승압된 데이터 신호는 RS232C 라고 불리는 케이블을 통해서 외장 모뎀에 연결된다. )
이를 단순화 시키면 결국 두 장치간의 UART 통신이라는 것을 알 수 있다. UART는 위와 같은 인터넷 연결뿐만 아니라 임베디드 기기안에서 여러 장치간의 통신에 아주 많이 사용되는 방법이다. (기기안에서의 UART 통신에는 승압이 필요 없으므로 레벨 쉬프터를 사용할 필요가 없다.)
보통 임베디드 기기 안에서의 UART 통신에서는 대부분의 경우 HDLC라는 프로토콜을 사용하거나 혹은 더 간단하게 개발자들이 자체적으로 프로토콜을 정의하여 사용한다. 사실 PPP도 표준 HDLC 프로토콜이 조금 변형된 형태이며, 여기에 클라이언트가 서버에 접속하기 위한 Authentication, Compression, Error detection, multilink 기능등이 추가된 프로토콜이다. 따라서 임베디드 기기안에서의 UART 통신을 위해서는 굳이 HDLC프로토콜을 놔두고 PPP를 사용할 필요는 없다.
HDLC에 대해서는 아래 사이트를 참조하자.
http://www.interfacebus.com/Design_HDLC.html
하지만 때로는 필요 없을 법 했던 것이 필요해지는 경우도 있는 법. 두 장치가 UART로 연결되어 있는 상황에서 HDLC와 PPP 연결 시 실측 throughput을 비교해 보아야 할 경우가 생겼다.
--- 꼭 이런 상황이 아니라도, UART로 연결 된 두 장치간에 IP를 할당하고 socket프로그래밍을 통해 통신을 하고자 한다면, HDLC대신 PPP를 사용해야 한다.
하여간 이런 경우에 PPP를 쓰는것은 위에서 예로든 인터넷 연결을 위한 Dial up 네트워크 연결 보다 훨씬 간단한데, 이유는 Authenticaiton등을 위한 설정이 필요 없기 때문이다.
아래는 QNX OS상에서 pppd을 실행시켜 연결하는 방법이다. 아마 리눅스나 다른 유닉스에서도 비슷하게 동작이 가능할 것이다.
Receiver(Server) :
/usr/sbin/pppd debug defaultroute /dev/ser4 updetach -crtscts 1000000 netmask 255.255.255.0 10.10.10.13:10.10.10.12 &
Sender(Client) :
/usr/sbin/pppt debug defaultroute /dev/ser4 updetach -crtscts 1000000 netmask 255.255.255.0 10.10.10.12:10.10.10.13 &
이와 같이 설정시 PPP의 Throughput 측정 결과는 Baud rate이 1Mbps일 때473Kbps로 측정되었다.
(동일 조건에서 HDLC는 685Kbps가 측정되었다. )
PPP를 사용했을 때는 그 위에 TCP/IP를 거쳐서 사용하게 되므로 HDLC를 사용하였을 때 보다 오버헤드가 클 것이라는 점에서 위 데이터는 쉽게 수긍이 가는 수치인 것 같다.
주의할 것은 UART 디바이스와 UART 디바이스 드라이버의 설정 그리고 HDLC 프로토콜의 구현 방법에 따라 Throughput과 CPU 점유율이 크기 달라질수 있다는 점이다. 보통 UART는 1Mbps와 같이 빠른 속도로는 잘 설정하지 않는데, 이는 UART가 다소 옛 기술이라 이런 고속 동작시 CPU 사용율이 높아지기 때문에다. 특히 CPU 사용율은 데이터를 read하는 횟수와 상관 관계가 큰데 이는 read가 unix시스템에서의 시스템 콜로, 시스템 콜이 불리는 횟수가 CPU 사용율과 관계가 무척 크기 때문이다. -- 시스템 콜이 불리면 user모드에서 kernel모드로 전환하기 위해 CPU가 할 일이 무척 많다.
이 CPU 점유율 문제는 TX쪽 보다 RX쪽에서 크게 발생하는데 이는 보내는 쪽은 보내고 싶은 데이터를 한번에 write로 보낼 수 있지만, read쪽은 보내는쪽에서 한번에 보내는 크기를 모르면 여러차례에 걸쳐 read 시스템 콜을 호출하여야 하기 때문이다.
Read 쪽에서 CPU사용율을 최소화 하기 위해 시스템 콜이 자주 발생하지 않도록 한번에 많은 데이터를 읽는 것이 유리하지만, 이 경우 원하는 만큼의 데이터가 RX되지 않으면 읽기 함수가 Block되어 빠른 데이터 처리가 어렵다. 따라서 보통은 N byte 가 읽혀지거나 N byte가 RX되지 못해도 M msec이후에는 Read 함수가 return되도록 설정하여야 한다. - readcon() 참조
또한 시스템에 따라 특정 데이터를 검출하여 해당 데이터가 RX될 때 Read함수를 return해주는 기능을 제공하기도 한다.(POSIX 호환은 아님) 이런 경우 보통 0x7E가 HDLC나 PPP에서 frame의 시작과 끝을 나타내는데 사용되므로, 0x7E를 지정하여 read 함수의 호출 횟수를 최적화하면 많은 성능 향상을 가져올 수 있다.
그만큼 오래되고 내용도 자못 복잡하여 해당 기술의 역사와 내용을 완전히 이해하기 쉽지 않지만 (항상 그러하듯) 실제로 사용하기 위해서 모든 것을 알 필요는 없다.
일단 서버와 클라이언트상에 PPP연결은 아래와 같이 이루어진다.
서버-모뎀----------------------------모뎀-클라이언트
여기서 서버는 인터넷 제공업체의 컴퓨터, 클라이언트는 가정집의 컴퓨터라고 생각하면 된다.
모뎀을 외장 모뎀이라고 가정하면, 서버-모뎀 혹은 모뎀-클라이언트는 시리얼 포트(COM포트)를 통하여 연결되어 있을 것이고, 시리얼 포트는 내부적으로 레벨 쉬프터를 거쳐 UART 장치에 연결될 것이다. 즉 아래와 같을 것이란 얘기.
서버의 UART 장치 - 레벨 쉬프터 - COM포트 - 외장 모뎀 ------------------>>>>
>>>>-----------------외장모뎀 - COM포트 - 레벨 쉬프터 - 클라이언트의 UART장치.
먼거리의 서버와 클라이언트를 연결하기 위하여 중간에 여러가지 장치를 거치지만 결국은 서버의 UART 장치와 클라이언트의 UART 장치간의 통신을 위한 프로토콜 되겠다. 뭐가? PPP가.
(참조:
UART는 3.3V를 사용하는데 컴퓨터 외부의 외장모뎀으로 데이터 전송시 데이터가 확실히 전달되도록 12V로 전압을 높여준다. 바로 레벨 쉬프터는 이때문에 필요하다. 이렇게 12V로 승압된 데이터 신호는 RS232C 라고 불리는 케이블을 통해서 외장 모뎀에 연결된다. )
서버 UART <----->클라이언트 UART
이를 단순화 시키면 결국 두 장치간의 UART 통신이라는 것을 알 수 있다. UART는 위와 같은 인터넷 연결뿐만 아니라 임베디드 기기안에서 여러 장치간의 통신에 아주 많이 사용되는 방법이다. (기기안에서의 UART 통신에는 승압이 필요 없으므로 레벨 쉬프터를 사용할 필요가 없다.)
보통 임베디드 기기 안에서의 UART 통신에서는 대부분의 경우 HDLC라는 프로토콜을 사용하거나 혹은 더 간단하게 개발자들이 자체적으로 프로토콜을 정의하여 사용한다. 사실 PPP도 표준 HDLC 프로토콜이 조금 변형된 형태이며, 여기에 클라이언트가 서버에 접속하기 위한 Authentication, Compression, Error detection, multilink 기능등이 추가된 프로토콜이다. 따라서 임베디드 기기안에서의 UART 통신을 위해서는 굳이 HDLC프로토콜을 놔두고 PPP를 사용할 필요는 없다.
HDLC에 대해서는 아래 사이트를 참조하자.
http://www.interfacebus.com/Design_HDLC.html
하지만 때로는 필요 없을 법 했던 것이 필요해지는 경우도 있는 법. 두 장치가 UART로 연결되어 있는 상황에서 HDLC와 PPP 연결 시 실측 throughput을 비교해 보아야 할 경우가 생겼다.
--- 꼭 이런 상황이 아니라도, UART로 연결 된 두 장치간에 IP를 할당하고 socket프로그래밍을 통해 통신을 하고자 한다면, HDLC대신 PPP를 사용해야 한다.
하여간 이런 경우에 PPP를 쓰는것은 위에서 예로든 인터넷 연결을 위한 Dial up 네트워크 연결 보다 훨씬 간단한데, 이유는 Authenticaiton등을 위한 설정이 필요 없기 때문이다.
아래는 QNX OS상에서 pppd을 실행시켜 연결하는 방법이다. 아마 리눅스나 다른 유닉스에서도 비슷하게 동작이 가능할 것이다.
Receiver(Server) :
/usr/sbin/pppd debug defaultroute /dev/ser4 updetach -crtscts 1000000 netmask 255.255.255.0 10.10.10.13:10.10.10.12 &
Sender(Client) :
/usr/sbin/pppt debug defaultroute /dev/ser4 updetach -crtscts 1000000 netmask 255.255.255.0 10.10.10.12:10.10.10.13 &
이와 같이 설정시 PPP의 Throughput 측정 결과는 Baud rate이 1Mbps일 때473Kbps로 측정되었다.
(동일 조건에서 HDLC는 685Kbps가 측정되었다. )
PPP를 사용했을 때는 그 위에 TCP/IP를 거쳐서 사용하게 되므로 HDLC를 사용하였을 때 보다 오버헤드가 클 것이라는 점에서 위 데이터는 쉽게 수긍이 가는 수치인 것 같다.
주의할 것은 UART 디바이스와 UART 디바이스 드라이버의 설정 그리고 HDLC 프로토콜의 구현 방법에 따라 Throughput과 CPU 점유율이 크기 달라질수 있다는 점이다. 보통 UART는 1Mbps와 같이 빠른 속도로는 잘 설정하지 않는데, 이는 UART가 다소 옛 기술이라 이런 고속 동작시 CPU 사용율이 높아지기 때문에다. 특히 CPU 사용율은 데이터를 read하는 횟수와 상관 관계가 큰데 이는 read가 unix시스템에서의 시스템 콜로, 시스템 콜이 불리는 횟수가 CPU 사용율과 관계가 무척 크기 때문이다. -- 시스템 콜이 불리면 user모드에서 kernel모드로 전환하기 위해 CPU가 할 일이 무척 많다.
이 CPU 점유율 문제는 TX쪽 보다 RX쪽에서 크게 발생하는데 이는 보내는 쪽은 보내고 싶은 데이터를 한번에 write로 보낼 수 있지만, read쪽은 보내는쪽에서 한번에 보내는 크기를 모르면 여러차례에 걸쳐 read 시스템 콜을 호출하여야 하기 때문이다.
Read 쪽에서 CPU사용율을 최소화 하기 위해 시스템 콜이 자주 발생하지 않도록 한번에 많은 데이터를 읽는 것이 유리하지만, 이 경우 원하는 만큼의 데이터가 RX되지 않으면 읽기 함수가 Block되어 빠른 데이터 처리가 어렵다. 따라서 보통은 N byte 가 읽혀지거나 N byte가 RX되지 못해도 M msec이후에는 Read 함수가 return되도록 설정하여야 한다. - readcon() 참조
또한 시스템에 따라 특정 데이터를 검출하여 해당 데이터가 RX될 때 Read함수를 return해주는 기능을 제공하기도 한다.(POSIX 호환은 아님) 이런 경우 보통 0x7E가 HDLC나 PPP에서 frame의 시작과 끝을 나타내는데 사용되므로, 0x7E를 지정하여 read 함수의 호출 횟수를 최적화하면 많은 성능 향상을 가져올 수 있다.
2010년 6월 23일 수요일
공개키 암호와 안드로이드 서명
컴퓨터 세계에서 공개키 암호를 사용하는 이유는 크게 두 가지로 나눌 수 있는데, 첫번째는 데이터를 보내는 사람을 확인하기 위함이고, 두번째는 데이터를 받는 사람을 확인하기 위함이다.
데이터를 보내는 사람을 확인: 전자서명용
특정인을 사칭하지 못하도록 하기 위함이며, 대표적인 사용 예로는 공인 인증서가 있다.
공인 인증서의 경우, 사용자는 제 3기관에서 발행한 공개키와 개인키 쌍을 발급 받으며, 이 중 공개키는 거래를 원하는 금융기관에 등록한다. 이 후 금융 거래 시 개인키로 암호화 된 개인 서명을 금융기관에 보내면, 금융기관은 이를 공개키로 풀어 개인 서명을 확인한다. 다른 사람의 개인키로 암호화한 전자 서명은 금융기관에 등록 된 공개키로는 풀리지 않으므로, 타인의 사칭을 막을 수 있다. 또다른 예는 ActiveX로 악의적 코드가 다른 회사나 개발자를 사칭하여 배포되지 않도록 전자 서명을 사용한다.
데이터 암호화: 데이터를 보내는 사람의 개인키 사용
데이터 복호화: 데이터를 보내는 사람의 공개키 사용
데이터를 받는 사람을 확인:
보내는 데이터를 안전하게 특정 수신인에게만 전달 되도록 하기를 원하는 경우이다. 이 경우 데이터를 받으려는 사람이 공개키와 개인키 쌍을 생성해서 공개키를 데이터를 보내주는 사람에게 전달하고, 데이터를 보내는 사람은 이 공개키를 사용하여 데이터를 암호화 한다. 이제 암호화된 데이터는 암호시 사용된 공개키와 쌍을 이루는 개인키를 사용하여야만 해독할 수 있으므로, 데이터 중간에 누군가 가로채어도 내용을 알 수 없게 된다.
데이터 암호화: 데이터를 받는 사람의 공개키 사용
데이터 복호화: 데이터를 받는 사람의 개인키 사용
안드로이드 애플리케이션 서명 - 데이터를 보내는 사람을 확인:
안드로이드에서는 애플리케이션 등록자를 확인하기 위해서 애플리케이션을 안드로이드 마켓에 등록할 때 애플리케이션에 전자 서명을 하여 제출하여야 한다. 이를 위해 개발자는 keytool이라는 프로그램을 사용하여 공개키/개인키 쌍을 생성하고 이 중 개인키를 애플리케이선에 전자 서명을 하기 위해서 사용 한다. 공개키는 애플리케이션을 배포할 때 함께 배포하며, 이는 애플리케이션이 설치될 때 개인키로 암호화 된 전자 서명을 확인하기 위해서 사용된다. 이로써 누군가 특정 개발자를 사칭하여 악성 코드를 배포할 수 없게 된다.
참고
1. keytool로 생성된 공개키/개인키 쌍은, 암호(패스워드)로 보호되며 key store라고 불리는 파일에 저장된다.
2. 애플리케이션에 전자 서명은 jarsigner라는 명령으로 할 수 있다. jarsigner명령 수행시 인자로 공개키/개인키가 저장되어 있는 keystore 파일과 서명을 원하는 애플리케이션 패키지 파일(*.apk)을 넘겨주게 된다. 안드로이드 1.5이상에서는 jarsigner를 직접 사용하지 않고 Eclipse안에서 서명을 수행할 수 있다.
뱀다리
혹시 왜 암호와 복호 모두에 사용 가능한 하나의 비밀키를 사용하지 않고 키를 공개키와 개인키로 나누는지 이해가 되지 않는가? 이는 비밀키의 경우 키를 전달 할 때 키가 제 3자에게 누출되는 것을 막을 수 없기 때문이다.(인터넷으로 키가 전송되는 경우를 생각해 보자) 암호와 복호에 동일한 키가 사용될 경우 3자에게 해당 키가 누출되면 더이상 데이터 보안이 불가능해 진다. 공개키/개인키를 사용할 경우 공개키는 전달되는 과정에서 3자에게 누출되어도 상관없으며, 개인키는 개인이 보관하며 타인에게 전송하지 않으므로 누출되지 않도록 해야 한다. 또한 개인키는 일반적으로 비밀키로 한번 더 암호화 하여 보관한다.즉 개인키를 가진 사람만 데이터 복호화가 가능하다.(데이터를 받는 사람을 확인하는 경우, 데이터를 보내는 사람을 확인하는 경우라면, 개인키를 가진 사람만 데이터 암호화(전자서명)이 가능)
데이터를 보내는 사람을 확인: 전자서명용
특정인을 사칭하지 못하도록 하기 위함이며, 대표적인 사용 예로는 공인 인증서가 있다.
공인 인증서의 경우, 사용자는 제 3기관에서 발행한 공개키와 개인키 쌍을 발급 받으며, 이 중 공개키는 거래를 원하는 금융기관에 등록한다. 이 후 금융 거래 시 개인키로 암호화 된 개인 서명을 금융기관에 보내면, 금융기관은 이를 공개키로 풀어 개인 서명을 확인한다. 다른 사람의 개인키로 암호화한 전자 서명은 금융기관에 등록 된 공개키로는 풀리지 않으므로, 타인의 사칭을 막을 수 있다. 또다른 예는 ActiveX로 악의적 코드가 다른 회사나 개발자를 사칭하여 배포되지 않도록 전자 서명을 사용한다.
데이터 암호화: 데이터를 보내는 사람의 개인키 사용
데이터 복호화: 데이터를 보내는 사람의 공개키 사용
데이터를 받는 사람을 확인:
보내는 데이터를 안전하게 특정 수신인에게만 전달 되도록 하기를 원하는 경우이다. 이 경우 데이터를 받으려는 사람이 공개키와 개인키 쌍을 생성해서 공개키를 데이터를 보내주는 사람에게 전달하고, 데이터를 보내는 사람은 이 공개키를 사용하여 데이터를 암호화 한다. 이제 암호화된 데이터는 암호시 사용된 공개키와 쌍을 이루는 개인키를 사용하여야만 해독할 수 있으므로, 데이터 중간에 누군가 가로채어도 내용을 알 수 없게 된다.
데이터 암호화: 데이터를 받는 사람의 공개키 사용
데이터 복호화: 데이터를 받는 사람의 개인키 사용
안드로이드 애플리케이션 서명 - 데이터를 보내는 사람을 확인:
안드로이드에서는 애플리케이션 등록자를 확인하기 위해서 애플리케이션을 안드로이드 마켓에 등록할 때 애플리케이션에 전자 서명을 하여 제출하여야 한다. 이를 위해 개발자는 keytool이라는 프로그램을 사용하여 공개키/개인키 쌍을 생성하고 이 중 개인키를 애플리케이선에 전자 서명을 하기 위해서 사용 한다. 공개키는 애플리케이션을 배포할 때 함께 배포하며, 이는 애플리케이션이 설치될 때 개인키로 암호화 된 전자 서명을 확인하기 위해서 사용된다. 이로써 누군가 특정 개발자를 사칭하여 악성 코드를 배포할 수 없게 된다.
참고
1. keytool로 생성된 공개키/개인키 쌍은, 암호(패스워드)로 보호되며 key store라고 불리는 파일에 저장된다.
2. 애플리케이션에 전자 서명은 jarsigner라는 명령으로 할 수 있다. jarsigner명령 수행시 인자로 공개키/개인키가 저장되어 있는 keystore 파일과 서명을 원하는 애플리케이션 패키지 파일(*.apk)을 넘겨주게 된다. 안드로이드 1.5이상에서는 jarsigner를 직접 사용하지 않고 Eclipse안에서 서명을 수행할 수 있다.
뱀다리
혹시 왜 암호와 복호 모두에 사용 가능한 하나의 비밀키를 사용하지 않고 키를 공개키와 개인키로 나누는지 이해가 되지 않는가? 이는 비밀키의 경우 키를 전달 할 때 키가 제 3자에게 누출되는 것을 막을 수 없기 때문이다.(인터넷으로 키가 전송되는 경우를 생각해 보자) 암호와 복호에 동일한 키가 사용될 경우 3자에게 해당 키가 누출되면 더이상 데이터 보안이 불가능해 진다. 공개키/개인키를 사용할 경우 공개키는 전달되는 과정에서 3자에게 누출되어도 상관없으며, 개인키는 개인이 보관하며 타인에게 전송하지 않으므로 누출되지 않도록 해야 한다. 또한 개인키는 일반적으로 비밀키로 한번 더 암호화 하여 보관한다.즉 개인키를 가진 사람만 데이터 복호화가 가능하다.(데이터를 받는 사람을 확인하는 경우, 데이터를 보내는 사람을 확인하는 경우라면, 개인키를 가진 사람만 데이터 암호화(전자서명)이 가능)
2010년 6월 18일 금요일
비디오 신호 전송 인터페이스
임베디드 시스템에서 많이 사용하는 비디오 신호 전송 인터페이스 방법을 정리하였다.
Parallel RGB:
RGB 각각 m bit씩 3 x m 개의 데이터 라인과 hsync. vsync. 라인등을 사용한 가장 기본적인 비디오 신호 전송 방법. 기기에 내장된 LCD모듈로 영상을 전송하기 위하여 임베디드 시스템에서 가장 일반적으로 사용하는 IF.
LVDS(Low Voltage difference Signaling):
고속 데이터 전송을 위해 꼬인 구리선으로 차신호를 보내는 방법으로 일반 데이터 전송(firewire등) 뿐만 아니라 비디오 데이터 전송에 사용된다. Parallel RGB보다 훨씬 적은 수의 라인으로 구성되므로 디스플레이 패널이 기기 외부에 있을때 많이 사용됨. 이름의 LV(Low Voltage)는 5V나 3.3V 가 아닌 1.5V를 사용하기 때문에 붙은 것임. 이름에서 알 수 있듯이 차신호를 보냄으로써 노이즈에 강하다.
디지털 테스트 시스템을 위한 LVDS 이해하기
노트북PC와 TV까지 '포스트 LVDS' 도입 물결
(영어버젼:http://blog.naver.com/jkhan012?Redirect=Log&logNo=150084746813)
TMDS(Transition Minimized Differential Signaling):
DVI와 HDMI에서 사용되는 고속 시리얼 데이터 전송 기술. LVDS와 유사한 기술로 RGB 채널별로 한개의 twisted-pair를 사용하여 차신호를 보낸다. DVI나 HDMI 모두 TMDS를 사용.
http://en.wikipedia.org/wiki/Transition_Minimized_Differential_Signaling
TSI(Transport Stream Interface):
MPEG 비디오 데이터를 전송하기 위해 사용되는 인터페이스.
TDAT, TCLK, TSYN,TVAL 4라인으로 구성됨.
PinName : Description : Master : Slave
---------------------------------------------
TDAT Data Output Input
TCLK Clock Output Input
TVAL Data Valid Output Input
TSYN Packet Sync. Output Input
참고자료:
디지털 시대의 비디오 신호조작기술
Analog 비디오 신호를 Digital Parallel RGB로 바꾸어주는 IC
Digital Parallel RGB를 LVDS로 바꾸어주는 IC
Parallel RGB:
RGB 각각 m bit씩 3 x m 개의 데이터 라인과 hsync. vsync. 라인등을 사용한 가장 기본적인 비디오 신호 전송 방법. 기기에 내장된 LCD모듈로 영상을 전송하기 위하여 임베디드 시스템에서 가장 일반적으로 사용하는 IF.
LVDS(Low Voltage difference Signaling):
고속 데이터 전송을 위해 꼬인 구리선으로 차신호를 보내는 방법으로 일반 데이터 전송(firewire등) 뿐만 아니라 비디오 데이터 전송에 사용된다. Parallel RGB보다 훨씬 적은 수의 라인으로 구성되므로 디스플레이 패널이 기기 외부에 있을때 많이 사용됨. 이름의 LV(Low Voltage)는 5V나 3.3V 가 아닌 1.5V를 사용하기 때문에 붙은 것임. 이름에서 알 수 있듯이 차신호를 보냄으로써 노이즈에 강하다.
디지털 테스트 시스템을 위한 LVDS 이해하기
노트북PC와 TV까지 '포스트 LVDS' 도입 물결
(영어버젼:http://blog.naver.com/jkhan012?Redirect=Log&logNo=150084746813)
TMDS(Transition Minimized Differential Signaling):
DVI와 HDMI에서 사용되는 고속 시리얼 데이터 전송 기술. LVDS와 유사한 기술로 RGB 채널별로 한개의 twisted-pair를 사용하여 차신호를 보낸다. DVI나 HDMI 모두 TMDS를 사용.
http://en.wikipedia.org/wiki/Transition_Minimized_Differential_Signaling
TSI(Transport Stream Interface):
MPEG 비디오 데이터를 전송하기 위해 사용되는 인터페이스.
TDAT, TCLK, TSYN,TVAL 4라인으로 구성됨.
PinName : Description : Master : Slave
---------------------------------------------
TDAT Data Output Input
TCLK Clock Output Input
TVAL Data Valid Output Input
TSYN Packet Sync. Output Input
참고자료:
디지털 시대의 비디오 신호조작기술
Analog 비디오 신호를 Digital Parallel RGB로 바꾸어주는 IC
Digital Parallel RGB를 LVDS로 바꾸어주는 IC
2010년 6월 16일 수요일
안드로이드에서 C만으로 프로그램 개발하기
많은 분들이 이미 고민해 주시고 해결책을 찾아 주셔서 관련 사이트를 링크만 한다.
먼저 일반적인 NDK를 사용하여 C사용하는 방법...
Being a Developer -
- Android NDK를 이용한 C/C++ 안드로이트 프로그래밍 Hello JNI
이제, Java없이 C로 실행파일까지 만들어 버리는 방법을 살펴 보자.
오가네 - 어느 프로그래머의 책 읽기
- 안드로이드(Android) NDK로 실행 파일 만드는 법
- 안드로이드(Android)NDK 실행파일 프로젝트 예제
- android-gcc
博而不精
- 윈도우에서 c로 안드로이드 어플 개발하기
기본적으로 NDK를 사용하여 C 실행 파일 생성 및 실행이 가능하지만, 만일 안드로이드가 지원하는 ARM 플래폼이 아니거나 NDK이외의 gcc 컴파일러 사용이 필요할 경우 이것도 불가능하지 않다. 해당 내용은 "Java와 C를 이용한 프로 안드로이드 게임 개발"에 서 찾아볼 수 있다.
먼저 일반적인 NDK를 사용하여 C사용하는 방법...
Being a Developer -
- Android NDK를 이용한 C/C++ 안드로이트 프로그래밍 Hello JNI
이제, Java없이 C로 실행파일까지 만들어 버리는 방법을 살펴 보자.
오가네 - 어느 프로그래머의 책 읽기
- 안드로이드(Android) NDK로 실행 파일 만드는 법
- 안드로이드(Android)NDK 실행파일 프로젝트 예제
- android-gcc
博而不精
- 윈도우에서 c로 안드로이드 어플 개발하기
기본적으로 NDK를 사용하여 C 실행 파일 생성 및 실행이 가능하지만, 만일 안드로이드가 지원하는 ARM 플래폼이 아니거나 NDK이외의 gcc 컴파일러 사용이 필요할 경우 이것도 불가능하지 않다. 해당 내용은 "Java와 C를 이용한 프로 안드로이드 게임 개발"에 서 찾아볼 수 있다.
2010년 5월 19일 수요일
정체불명의 로그 추적하기.
개발 중 재현이 어려운 문제를 해결하기 위해 logger box를 사용한 몇 주간의 exposure test 끝에 문제를 재현하였는데 도대체 누가 출력했는지 알 수 없는 로그가 발견되었다. 이걸 어떤 모듈(실행중인 프로그램)에서 출력하는지 손쉽게 알 수 있는 방법이 없을까 고민하다가 아래와 같은 방법을 사용하였다.
bash-2.03$ find . -exec strings {} -f \; | grep "XXXX"
도대체 사용할 일 없어보였던 strings 명령을 실전에 최초로 사용한 케이스 되겠다.
보너스로, 특정 바이너리가 사용하는(필요로하는) so파일 찾는 법은 아래와 같다.
bash-2.03$ readelf -a binaryname | grep NEEDED
bash-2.03$ find . -exec strings {} -f \; | grep "XXXX"
도대체 사용할 일 없어보였던 strings 명령을 실전에 최초로 사용한 케이스 되겠다.
보너스로, 특정 바이너리가 사용하는(필요로하는) so파일 찾는 법은 아래와 같다.
bash-2.03$ readelf -a binaryname | grep NEEDED
2010년 4월 22일 목요일
Linux 토막 지식
- 부트 옵션 "root=/dev/ram" 는, 부팅 종료 후에도 initrd를 폐기하지 않고 root file system으로 사용하겠다는 뜻이다. 즉 별도의 flash나 HDD등에 root file system을 만들지 않는 경우에 사용하는 옵션이다.
- 부팅 옵션은 .config파일의 CONFIG_CMDLINE 항목에 지정할 수 있다. 혹은 menuconfig->Boot options->Default kernel command string에서 지정한다.
- 부팅 중 initrd안에 linuxrc script가 실행되고, 실행이 끝나면 일반적으로 initrd는 폐기된다.
- 별도의 root file system이 존재할 때 root file system에 /initrd 디렉토리가 있을 경우, 부팅 종료 후 initrd가 폐기되지 않고, /initrd에 mount된다.
- vmlinux파일. ELF type
- Image. raw binary file
- zImage. Image를 gz압축한것
- bzImage. i386의 real mode 1M 메모리 제약을 위해 일정 크기 이상의 큰 kernel에서 사용.
- make mrproper : 커널소스를 초기 상태로 되돌린다. .config파일까지 초기화되므로 주의. mrproper는
참고 자료:
- uImage와 zImage차이설명
- 임베디드 시스템 엔지니어를 위한 리눅스 커널 분석
- mount
- 부팅 옵션은 .config파일의 CONFIG_CMDLINE 항목에 지정할 수 있다. 혹은 menuconfig->Boot options->Default kernel command string에서 지정한다.
- 부팅 중 initrd안에 linuxrc script가 실행되고, 실행이 끝나면 일반적으로 initrd는 폐기된다.
- 별도의 root file system이 존재할 때 root file system에 /initrd 디렉토리가 있을 경우, 부팅 종료 후 initrd가 폐기되지 않고, /initrd에 mount된다.
- vmlinux파일. ELF type
- Image. raw binary file
- zImage. Image를 gz압축한것
- bzImage. i386의 real mode 1M 메모리 제약을 위해 일정 크기 이상의 큰 kernel에서 사용.
- make mrproper : 커널소스를 초기 상태로 되돌린다. .config파일까지 초기화되므로 주의. mrproper는
참고 자료:
- uImage와 zImage차이설명
- 임베디드 시스템 엔지니어를 위한 리눅스 커널 분석
- mount
vi에서 ^M 제거하기
:1,$s/^M//g
혹은
:%s/^M//
1,$ : 첫번째 라인에서 $(마지막) 라인까지 적용.
여기서 1,$ 대신 모든 라인을 뜻하는 % 로 바꾸어 사용할 수 있음.
s : substitute .
/ : 구분자
^M : Ctrl Key + v key + m key 를 차례로 모두 누를것. 누르는 동안 앞에 누른 키를 계속 누르고 있을 것.
// : 두 구분자 사이에 아무것도 없으므로 ^M이 아무것도 없는 것으로 치환됨 .
g: 한 라인에서 ^M이 여러개 있을 경우 이들 모두를 바꾸기 위해서 사용. 여기서는 한 라인의 마지막에만 ^M이 있으므로 굳이 g를 사용할 필요가 없다.
참고
^:캐럿: 정규식에서 문장의 시작 위치를 뜻함. vi에서 "^"를 누르면 해당 라인의 첫 글자로 이동. 반면에 "0"(Zero)을 누르면 행의 첫 글자가 아닌 행의 첫번째 열로 이동. 하지만 위의 ^M앞의 ^는 이것과 상관없는 control문자를 뜻함.
$:달러: 끝의 의미가 있음. 여기서는 마지막 라인을 의미, 정규식에서 사용되면 문장의 끝을 의미. vi에서 "$"을 누르면 현재 행의 마지막열로 이동함.
혹은
:%s/^M//
1,$ : 첫번째 라인에서 $(마지막) 라인까지 적용.
여기서 1,$ 대신 모든 라인을 뜻하는 % 로 바꾸어 사용할 수 있음.
s : substitute .
/ : 구분자
^M : Ctrl Key + v key + m key 를 차례로 모두 누를것. 누르는 동안 앞에 누른 키를 계속 누르고 있을 것.
// : 두 구분자 사이에 아무것도 없으므로 ^M이 아무것도 없는 것으로 치환됨 .
g: 한 라인에서 ^M이 여러개 있을 경우 이들 모두를 바꾸기 위해서 사용. 여기서는 한 라인의 마지막에만 ^M이 있으므로 굳이 g를 사용할 필요가 없다.
참고
^:캐럿: 정규식에서 문장의 시작 위치를 뜻함. vi에서 "^"를 누르면 해당 라인의 첫 글자로 이동. 반면에 "0"(Zero)을 누르면 행의 첫 글자가 아닌 행의 첫번째 열로 이동. 하지만 위의 ^M앞의 ^는 이것과 상관없는 control문자를 뜻함.
$:달러: 끝의 의미가 있음. 여기서는 마지막 라인을 의미, 정규식에서 사용되면 문장의 끝을 의미. vi에서 "$"을 누르면 현재 행의 마지막열로 이동함.
2010년 4월 8일 목요일
Linux Logging : syslogd vs klogd
syslogd는 유저 어플리케이션이 syslog APIs를 사용하여 남기는 로그를 기록하고 관리하기 위해서 사용되는 데몬이다. 하지만 커널 프로그램에서는 메세지를 남기기 위해서 사용자 어플리케이션용인 syslog APIs를 사용하지 못하기 때문에 syslogd으로 로그 메세지를 남길 수 없다. 따라서 커널 프로그램에서 printk를 사용하여 출력하는 메세지는 바로 syslogd로 가지 못하며, klogd이 받아 이를 syslogd으로 넘겨주게 된다. 참고로 유저 어플리케이션에서 syslogd로 메세지를 남길 때는 아래 함수들을 사용한다.
void openlog( char *ident, int option, int facility)
void syslog ( int priority, char *format, ...)
void closelog( void )
가장 낮은 로그레벨이 7이므로 위와 같이 8로 설정하면, 모든 커널 로그 메세지를 볼 수 있다.
참고 사이트:
http://www.linuxjournal.com/article/4036?page=0,2
#include < syslog.h >
void openlog( char *ident, int option, int facility)
void syslog ( int priority, char *format, ...)
void closelog( void )
커널 로그 메세지는 dmesg 명령으로 볼수 있으며, /proc/kmsg 에서도 확인할 수 있다.
#dmesg
혹은 klogd을 죽이고
#cat /proc/kmsg
printk는 커널내의 메모리상의 circular로깅 버퍼에 기록되므로 인터럽트 처리 루틴에서도 호출이 가능하다. klogd은 항상 이를 모니터링하며 데이터를 읽어서 syslogd로 보내주는데 이때 circular buffer가 clear되므로 /proc/kmsg를 사용하여 모니터링하고자 할 때는 klogd를 죽여야 한다.
만일 기대한 로그가 보이지 않는다면, 현재 로그 레벨이 너무 높아서일 수 있다. 높은 로그 레벨에서는 높은 우선 순위의(중요한) 메세지들만 기록된다. 로그 레벨은 값이 작을수록 높은 우선 순위를 가지며, 0~7사이의 값을 가진다.
아래 명령으로 현재 로그 레벨을 알 수 있다.
# cat /proc/sys/kernel/printk
4 4 1 7
이는 각각 현재 로그 레벨, 기본 로그 레벨, 최소 허용 로그 레벨, 부트시 기본 로그 레벨에 해당한다. 이중 현재 로그레벨은 아래와 같이 변경할 수 있다.
echo 8 > /proc/sys/kernel/printk가장 낮은 로그레벨이 7이므로 위와 같이 8로 설정하면, 모든 커널 로그 메세지를 볼 수 있다.
참고 사이트:
http://www.linuxjournal.com/article/4036?page=0,2
2010년 3월 11일 목요일
리눅스 드라이버 작성을 위한 Bottom Half 선택하기
리눅스 드라이버 작성 시 bottom half 처리가 필요할 경우 선택 가능한 몇 가지 방법이 있다. 필요에 따라 적절한 방법을 선택하면 되는데, 이를 위한 일반적(절대적이지는 않지만 대부분의 경우 잘 동작하는...)이고 간편한 선택 방법은 아래와 같다.
1. 해당 작업이 sleep이 가능하거나 sleep이 필요할 경우 : Work Queue
2. 1이 아니며 빠른 처리가 필수적인 경우: Tasklet
tasklet은 빠른 응답이 필요한 경우에 work queue보다 더 적합하지만 interrupt context에서 실행되므로 해당 작업 도중에 sleep이나 선점이 일어날 수 없다. tasklet은 softirq를 사용하여 구현되는데, 디바이스 드라이버 작성시에는 softirq보다 tasklet사용이 권장된다. 하지만 softirq 사용이 필요한 경우가 있을 수도 있다. softirq와 tasklet의 가장 구별되는 특징은 tasklet은 여러 tasklet이 동시에 실행되지 않음이 보장된다는 점이다. 따라서 동기화에 대한 고려가 덜 필요하므로 softirq 보다 쉽게 사용이 가능하다.
tasklet과 softirq와의 관계와 마찬가지로, work queue는 kernel thread를 사용되어 구현되어 있다. work queue는 kernel thread를 직접 사용하는 것 보다 훨씬 쉽게 사용할 수 있도록 구성되어 있을 뿐만 아니라 kernel thread를 직접 만들어서 사용할 때 할 수 있는 거의 모든 일을 work queue를 사용하여 구현할 수 있다. 따라서 디바이스 드라이버 작성자가 굳이 work queue대신 kernel thread를 직접 생성하여 사용할 필요가 없다. work queue는 kernel thread로 구현되었으므로 process context에서 실행되고 따라서 sleep이 가능하다. 대신 동기화에 대해서는 디바이스 드라이버 작성자가 직접 고려해 주어야 하며, process context지만 kernel thread이므로 user space에 대한 접근은 불가능하다.
1. 해당 작업이 sleep이 가능하거나 sleep이 필요할 경우 : Work Queue
2. 1이 아니며 빠른 처리가 필수적인 경우: Tasklet
tasklet은 빠른 응답이 필요한 경우에 work queue보다 더 적합하지만 interrupt context에서 실행되므로 해당 작업 도중에 sleep이나 선점이 일어날 수 없다. tasklet은 softirq를 사용하여 구현되는데, 디바이스 드라이버 작성시에는 softirq보다 tasklet사용이 권장된다. 하지만 softirq 사용이 필요한 경우가 있을 수도 있다. softirq와 tasklet의 가장 구별되는 특징은 tasklet은 여러 tasklet이 동시에 실행되지 않음이 보장된다는 점이다. 따라서 동기화에 대한 고려가 덜 필요하므로 softirq 보다 쉽게 사용이 가능하다.
tasklet과 softirq와의 관계와 마찬가지로, work queue는 kernel thread를 사용되어 구현되어 있다. work queue는 kernel thread를 직접 사용하는 것 보다 훨씬 쉽게 사용할 수 있도록 구성되어 있을 뿐만 아니라 kernel thread를 직접 만들어서 사용할 때 할 수 있는 거의 모든 일을 work queue를 사용하여 구현할 수 있다. 따라서 디바이스 드라이버 작성자가 굳이 work queue대신 kernel thread를 직접 생성하여 사용할 필요가 없다. work queue는 kernel thread로 구현되었으므로 process context에서 실행되고 따라서 sleep이 가능하다. 대신 동기화에 대해서는 디바이스 드라이버 작성자가 직접 고려해 주어야 하며, process context지만 kernel thread이므로 user space에 대한 접근은 불가능하다.
피드 구독하기:
글 (Atom)