2015.03.14 20:52


Windows PowerShell이라고 Windows 7 이상 사용자, 혹은 Windows XP 사용자도 Visual Studio를 쓰는 유저라면 모두 알고 있는 프로그램일 것입니다.


제가 처음 봤던 Windows PowerShell은 Windows Vista x64에서 봤었던 것이 처음이었습니다. 지금은 Windows Vista 유저가 많이 줄은 편이지만, 제가 베타테스터 이후 RTM이 나왔을 때 MS의 새로운 콘솔을 보여줬던 것이 지금의 PowerShell이었습니다. 하지만 처음 PowerShell을 봤을 때는 그냥 단순한 명령 프롬포트의 업그레이드판인줄 알았지만 그 이후 Windows Server 2008을 설치한 후 PowerShell이 서버 관리에 굉장히 유용한 요소였습니다. ㄱ-;; (어떻게 보면, 아닌 면도 있었지요)


PowerShell은 Python Shell과 유사할 수도 있습니다(?) 왜 그렇게 생각하냐면, 직접 PowerShell에서 명령어 코드를 사용하여 스크립트를 제작할 수 있다는 점이 Python Shell과 유사하다고 생각했기 때문입니다. 


그러나 처음 나왔던 PowerShell에서 정말 불편했던 것은 긴 명령어를 모두 기억해야한다는 단점이었습니다. 리눅스처럼 짧고 간결하면서 사용자가 쉽게 사용할 수 있는 프로그램이었다면, 정말 괜찮았을지도 모릅니다. 하지만 처음에 나왔던 Powershell 1.0은 명령어 보기를 직접 띄워서 일일이 찾아야한다는 단점을 가지고 있었습니다. 그 단점을 보완한 Powershell이 바로 Powershell 3.0과 같이 공개된 PowerShell ISE 프로그램이었습니다.




위에 보시는 것은 평범한 Powershell입니다. 이 커다란 창에서 Tab 키의 자동 완성만을 사용하여 매개변수와 파라미터를 받아내는 명령어를 직접 입력해야하며 설령 스크립트로 만들어 써도 그 기능이 어떠한 역할을 하는지 찾으려면 MSDN 문서를 참고해야 했습니다. 


위 사진은 PowerShell ISE의 화면입니다. 오른쪽에 명령어 도움 상자가 하나 추가되어 자신이 사용하고 싶은 명령어를 직접 색인하거나 사용할 수 있는 파라미터를 확인할 수 있는 데다가 직접 상자에 입력하면 긴 명령어를 PowerShell이 만들어서 명령을 대신해주기도 합니다.


PowerShell을 서버 OS의 입장에서 본다면, 리눅스의 SSH와 언듯 비슷합니다.  PowerShell ISE는 원격으로 서버나 클라이언트 윈도우 OS를 제어할 수 있고, 콘솔 서버 관리를 주로하는 리눅스 서버 유저가 윈도우 서버 유저로 갈아타기도 쉽다고 볼 수 있겠습니다. 다만 PowerShell의 불편한 점은 긴 명령어입니다. 이 긴 명령어를 간략화 하는 것은 MS의 숙제이며 계속 긴 명령어가 유지된다면, 관리나 사용하는 데 오히려 더 장애 요소가 될 수도 있습니다.


현 Windows Server 2012에서는 Powershell로 관리할 수 있는 명령어가 생각보다 많습니다. Windows Azure가 등장하면서 Powershell ISE는 원격으로 클라우드OS를 관리/제어하는데, 용이하지만 일반 윈도우 서버 유저에게 장애 요소가 한 가지 있습니다. 


실제 ISE로 가능한 실행 요소가 GUI에서는 없다는 것입니다. 대표적인 예로, 사용자 정책입니다. MS의 윈도우 서버는 보안상 기본값으로 패스워드를 3개월 이상 유지시킬 수 없도록 설정했습니다. Windows 8과 같은 클라이언트OS에서는 이를 그룹 정책이나 컴퓨터 관리 제어판을 통해서 옵션을 바꿀 수 있지만 윈도우 서버의 경우 Powershell을 사용하지 않으면 옵션을 변경할 수 없다는 단점을 가지고 있습니다. 어떻게 보면, MS가 Powershell의 사용 강제화 하려고하는 조짐도 약간 있는 것 같거나 아니면 정말 보안상 이런 용도로 해야만 했는지 검토해볼 필요가 있는 듯합니다.


결론


Windows PowerShell을 가끔 저도 사용하지만 긴 명령어 때문에 복잡한 것은 여전합니다. 명령어만 간략하다면 정말 유용한 툴이 될 수도 있을 법하고, 프롬포트 대체용으로 대화형 콘솔에 기본값으로 넣어도 될 정도입니다. 하지만 이는 전문가 혹은 개발자 중심으로 얘기하는 것입니다. 일반 사용자에게는 GUI가 더 익숙하고 좋겠지요? Powershell을 이용한 전문적인 사용도 차기 Windows에서 좀 더 개편될 수 있었으면 합니다.

신고


Posted by injunech
2015.03.14 20:15


JNA는 기존 JNI(Java Native Interface)의 복잡한 구현 방식을 단축하고자 나온 OpenSource Library이다.

https://github.com/twall/jna

JNA를 이용하면 JNI의 native library와의 연결을 위한 javah header파일 생성, native source 파일 생성, 컴파일 등의 과정이 불필요하며, 이미 만들어진 native library의 재사용이 가능하게 된다. 말 그대로 native access임..ㅎ

예 1) JNI 개발 과정

1) Native Method 선언된 Java Class 코딩
2) Java Class 컴파일
3) javah를 통한 C Header파일 생성
4) C 소스 코딩
5) C 소스 컴파일
6) Execute Java Class


예 2) JNA 개발 과정

1) Native Method 선언된 Java Class 코딩
2) Java Class 컴파일
3) Execute Java Class


참고로 최근에 많은 OpenSource들이 JNA를 이용하여 성능을 향상시키는 방식를 적용하고 있으며, 무엇보다도 지저분한 h,c 파일들이 프로젝트 내에서 사라지게 되어 매우 깔끔해지고 관리도 수월하다. ;)

다음은 JNA를 통해 test.so의 foo라는 함수를 호출하는 간단한 예제를 만들어 보았다.


1. TestLibrary Interface

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
 * Test Library Interface
 *
 * @Author Xenomity™ a.k.a P-slinc' (이승한)
 */
public interface TestLibrary extends Library {
    TestLibrary LIBRARY = (TestLibrary) Native.loadLibrary(("test.so"), TestLibrary.class);

    /**
     * foo method
     */
    void foo();  // native method
}


2. Test Result

TestLibrary.LIBRARY.foo();

...

[RESULT] foo function executed~~!.


신고

'Programming > JAVA' 카테고리의 다른 글

Java 문자열 숫자 자료형 변환  (0) 2016.11.14
[Java] Bluetooth Examples for javax.bluetooth.DiscoveryAgent  (0) 2015.05.18
JNA (Java Native Access)  (0) 2015.03.14
[JAVA] 자바 실행파일 만들기  (0) 2015.03.01
JGoodies JAVA Swing API  (0) 2015.02.07
클래스 java.io.File  (0) 2013.05.29


Posted by injunech
2015.03.13 17:16



모듈과 커널 버전

모듈은 커널 버전과 관련이 많습니다. 커널 버전에 맞춰서 모듈이 빌드되며, 커널의 버전과 모듈의 버전이 일치해야만 이용할 수 있습니다. 커널 소스에서 커널의 버전은 include /linux/version.h에서 확인할 수 있습니다.

#define UTS_RELEASE "2.6.14.6"
#define LINUX_VERSION_CODE 132622
#define KERNEL_VERSION(a,b,c) (((a) << 16 ) + ((b) <<8)  +  (c))

따라서, 특정 버전 이상에서만 동작하는 모듈이라던가, 커널 버전에 따라 다르게 동작하는 모듈을 작성하고 싶다면 이를 활용해서 다음과 같은 코드를 작성할 수 있습니다.

#if LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 10)
MODULE_PARM( user_name, "charp");
#else
MODUILE_PARM( user_name, "s");
#elseif

MODULE_PARM()의 의미나 사용법은 나중에 설명을 한다. 여기서는 VERSION_CODE와 KERNEL_VERSION()사용한 방식만 이해하면 됩니다. KERNEL_VERSION()은 커널 버전 번호를 받아서 정수값으로 만들어 줍니다.  해당하는 커널 버전을 미리 정수 값으로 만들어둔 것이 LINUX_VERSION_CODE이고, 이것은 모든 커널에 선언되어 있습니다.

모듈과 static 선언

모듈 안에서만 사용되는 변수나 함수에는 static 키워드가 선언되어 있습니다. static은 메모리 내에 정적으로 위치하게 만드는 할을 하기 때문에 해당 소스 코드 내에서 전역으로 사용될 수 있습니다. 변수에 사용되면 전역변수가 되며, 함수에 사용되면 전역 함수가 되겟지요. 실제로 .c 코드 안에서 사용되는 모든 C 함수나 함수 바깥에 선언된 변수는 어디서나 상ㅇ할 수 있기 때문에 어떤 의미로는 항상 전역이라고 할 수 있습니다. 함수나 전역 변수에 사용된 static 의 다른 의미는 다른 .c소스 코드에서 접근할 수 없게하는 범위 지정자 입니다.

리눅스 커널은 커널 전체가 하나의 프로그램입니다. 그러니까 같은 이름을 가진 변수나 함수를 만들 수 없습니다. 누군가 A라는 모듈에서 hello()함수를 작성해서 커널 영역에 로드했다면, 또 다른 hello() 함수를 가진 모듈 B는 로드 할 수 없게 됩니다. 이 함수가 모듈 안에서만 사용되고, 다른 커널에서 참조할 필요가 전혀 없다면 이런 파일들은 커널 영역에서 보이지 않게 해야 합니다. 때문에 static을 사용합니다. init_module()과 cleanup_module()함수는 다소 예외적인 경우로는 이 함수는 static을 사용하지 않아도 커널 영역에 공개 되지 않습니다. 실제로, 이들 함수는 __init_module_inline()과 __exit_module() 함수는 다소 예외적인 경우로 이 함수는 static을 사용하지 않아도 커널 영역에 공개 되지 않습니다.  실제로 이들 함수는 __init_module_inline()과 __exit_module_inline() 같은 인라인 함수로 대체되어 실행되고, 이들 함수는 모두 static으로 선언되어 있기 때문에 커널 영역에서 공개되지 않습니다. 커널 영역에 공개된 함수는 /proc/ksyms(2.4커널) 이나 /proc/kallsysms(2.6커널)에서 확인 할 수 있습니다.

typedef int (*__init_module_fun_t)(void)
                            └ init_module()의 원형
typedef void (*__cleanup_module_func_t)(void);
#define module_init(x) \              └ cleanup_module()의 원형
   int init_module(void) __attribute__(alias(#3))); \
   static inline _init_module_func_t __init_module_inline(void) \
    └  커널 영역에 고액되지 않는 지역 함수로 선언됩니다.
   {  return x; }

#define module_exit (x) \
  void cleanup_module(void) __attribute__((alias(#x))); \

  static inline __cleanup_module_func_t__cleanup_module_inline(void) \
    └  커널 영역에 고액되지 않는 지역 함수로 선언됩니다.
  { return x; }
static으로 선언되어 있으면, 외부 C 소스 코드에서 extern 선언으로 참조할 수 없습ㄴ디ㅏ. 2.5 커널에서는 모듈 내에서 static 없이 선언된 함수는 커널 영역에 공개되었지만 2.6에서는 공개되지 않았습니다.

모듈과 커널 심볼

모듈은 커널 영역에서 실행되기 때문에 표준 C 함수들은 사용할 수 없습니다. 대신에, 커널 영역에서 사용할 수 있는 함수나 자료 구조의 목록을 커널에서 제공합니다. 이 목록은 2.4 커널에서는 /proc/ksyms, 2.6 커널에서는 /proc/kallsyms를 통해 제공합니다. printk()함수도 커널 심볼 파일에서 확인할 수 있습니다.

2.6 커널의 심볼

# grep printk /proc/kallsyms
.........     ┌ 심폴의 타입 정보
c011d6b0  T printk
c011d6b0  T vprintk
c011d6b0  T __printk_ratelimit
........                               ┌ 심폴의 타입 정보
c011d6b0  U printk        [vmhgfs]
c011d6b0  U printk        [vmxnet]
      |            └ 심볼 이름
                 └ 심볼 이름

심볼 타입

설명

A

절대 주소로 변경되지 않음

B

bss 영역의 심볼

C

공용 심볼로 초기화되지 않은 변수를 의미

D

data 영역의 심볼로 초기화된 변수를 의미

R

rdata 영역, 즉 읽기 전용변수를 의미

T

text 영역의 심볼로 함수를 의미

U

해당 모듈에서 정의하지 않은 (undefined) 심폴을 의미

I

다른 심볼에 대한 간접(Indirect) 참조를 의미하는 GNU 확장

N

디버깅 심볼

- 심볼의 타입 -

printk() 함수를 사용하는 모듈이 있으면 printk()함수를 이용하는 모듈 이름과 함께 printk()에 대한 심볼 타입이 "U"로 나타납니다. 직접 작성한 모듈에서 printk() 함수를 정의한 것이 아니기 떄문에 그렇습니다. 심볼 타입이 대문자로 사용되면 전역 심볼을 의미하고, 소문자로 되어 있으면 지역 심볼을 의미합니다.


심볼 : 2.4와 2.6의 차이

2.4 커널에서는 모듈 안에서 static으로 선언되지 않은 함수들이 모두 커널 심볼로 공개되어 있습니다. 2.6커널에서는 static으로 선언되지 않은 함수여도, 커널 심볼로 등록 하지 않으면 공개되지 않게 변경되었습니다.

커널 심볼로 공개시키는 방법은 EXPORT_SYMBL()이나 EXPORT_SYMBOL_GPL()과 같은 매크로를 사용해서 공개할 심볼을 지정하기만 하면 됩니다. printk() 함수의 경우 kernel/printk.c 에서 다음과 같은 부분을 확인할 수 있습니다.

kernel/printk.c

EXPORT_SYMBOL(printk);

이와 같이 정의되어 있기 때문에 외부 심볼로 공개되어 있으며, 커널이나 모듈 내에서 자유롭게 사용할 수 있습니다.

2.4 커널의 심볼
[/usr/src/linux-2.4.x.x #] grep printk /proc/ksyms

       ┌ 커널 내 심볼의 시작 주소
c0114aa0 printk_R1b7d4074
                       
└ 커널 버전과 심볼의 CRC 정보를 합한 값

2.6 커널의 /proc/kallsyms에서는 버전 정보를 제공하지 않습니다.
심볼과 관련된 매크로는 include/linux/module.h에 정의되어 있으며 알아야 될 것은 다음과 같습니다.

종류

설명

EXPORT_SYMBOL(var)

심볼을 공개합니다.

EXPORT_SYMBOL_NOVERS(var)

심볼을 버전정보 없이 공개합니다.

EXPORT_SYMBOL_GPL(var)

EXPORT_SYMBOL과 동일 하지만 GPL과 호환되는 라이선스로 등록한 모듈에서만 심볼을 볼 수 있습니다.

EXPORT_NO_SYMBOLS

모듈 내에서 어떤 심볼도 공개하지 않음을 정의합니다.

 - 심볼 매크로  -

EXPORT_NO_SYMBOLS는 모듀 내의 어디서나 한 줄만 넣어주면 되며, 해당 모듈에서 어떤 심볼도 공개하지 않음을 의미합니다. EXPORT_SYMBOL_GPL()은 MODULE_LICENSE()과 관련이 깊습니다.

모듈의 라이선스

리눅스 커널은 GPL라이선스를 따릅니다. 그리고 GPL 라이선스가 적용된 소스 코드를 수정한 경우 수정된 소스 코드를 공개해야 합니다. 일부 업체들은 오픈 소스를 이용해서 제품을 개발하지만 수정된 소스 코드를 공개해야 합니다. 일부 업체들은 오픈 소스를 이용해서 제품을 개발하지만 수정된 소스 코드를 공개하지 않아 물의를 사기도 했습니다. 매년 라이선스와 관련된 분쟁이 증가하고 있습니다. 때문에 모듈에서도 제작자가 원하는 라이선스를 지정하도록 했으면, 이 라이선스를 지정하지 않으면, 오픈소스인 커널에 상업적인 코드가 추가될 수 있고, 이는 커널의 오픈 소스를 위배할 수 있다는 경고를 보여줍니다.

module license 'unspecified' taints kernel.

현재 까지는 MODULE_LICENSE()를 통해 라이선스를 명시하지 않아도 문제는 없지만, 이런 라이선스 논쟁 이후 EXPORT_SYMBOL_GPL()이 추가 되었습니다. 이는, GPL과 호환되는 라이선스를 지정하지 않은 모듈에서는 커널의 기능을 사용할 수 없게 하는 정책을 추가하기 위한 것으로, 현재 이와 관련된 불이익은 없지만, 필요한 경우 GPL 호환 라이선스를 따르지 않는 상업적 코드들은 GPL코드를 이용할 수 없게 하기 위한 조치를 반영한것입니다.

MODULE_LICENSE()를 통해 지저앟ㄹ 수 있는 라이선스는 다음과 같다.

라이선스 종류

의미

GPL

GNU Public License v2 또는 이상

GPL v2

GNU Public License v2

GPL and additional rights

GNU Public License v2 right and more

Dual BSD/GPL

GNU Public License v2 또는 BSD 라이선스 선택

DUAL MPL/GPL

GPL v2 또는 모질라 라이선스 선택

Proprietary

비자유 소프트웨어



출처 : 리눅스 커널 프로그래밍  저 한동훈,원일용, 하홍준  / 한빛 미디어

신고

'Programming > Linux/Unix' 카테고리의 다른 글

디바이스 트리 작성법 (2편)  (1) 2015.03.24
디바이스 트리 작성법 (1편)  (0) 2015.03.24
[Linux] Module 관련  (0) 2015.03.13
[Makefile] Kbuild 와 Module Compile  (0) 2015.03.09
[Makefile] Device Driver  (0) 2015.03.09
Makefile 문법 및 관련 내용  (0) 2015.03.09


Posted by injunech

티스토리 툴바