임베디드/Algorithm2009. 3. 2. 17:53

POSIX 함수에 대해 글 쓴 지가 너무 오래 전이라 까맣게 잊고 있었다. 오늘은 두서 없이 세마포어라는 놈을 건들여보도록 하자. 일단 세마포어 하면 유명한 예제가 있다. 철학자라는 것들이 가서 포크랑 나이프랑 한 벌 씩 더 가져오면 해결할 수 있는 문제를 굳이 앉아서 남이 썼던 것 더럽게 씻지도 않고 빌려쓰고... 암튼 그런 드러운 문제를 해결하기 위해 세마포어가 탄생했다...라고 하는데 드럽긴 마찬가지고 좀 그렇다. 세마포어 개념은 안드로메다 같은 곳에서 찾아보길 바란다. 그래도 귀찮은 사람은 세마포어를 들어갈 수 있는 사람 수를 한정한 매점(PX?)이라고 생각해도 좋을 것이다. '세마포어 값'은 매장에 들어갈 수 있는 사람 수 여분을 뜻한다.

일단 세마포어도 SysV에서 뛰쳐나온 
IPC개념인데, 일전에 알아봤던 것과 비슷한 API를 제공한다. semget, semop, semctl 이 바로 그것인데, 역시나 유명한 녀석이라 자세한 설명은 생략한다. 대충 semget으로 커널에 세마포어 객체 만들어달라고 떼를 쓴 뒤에 semop을 통해 세마포어 값을 증감하고, semctl을 통해 커널에 세마포어 객체 파괴하여 정리하는 역을 한다. 이 역시 IPC이므로 명시적으로 세마포어 객체를 커널에서 제거하지 않으면 리부팅할 때까지는 커널자원을 차지한다. - 설명 끝 -

이번에도 SysV는 별 관심사는 아니고, 세마포어 
개념을 거의 그대로 가져온 POSIX API가 있다. 아, 그전에 미리 설명해야할 것이 있는데, 세마포어에도 이름이 있는 녀석(named-)이 있고, 없는 녀석(unnamed-)이 있다. 뭐더게 이름 있고 없는 녀석을 만들었는지는 각자가 판단해야할 것 같지만, 보통 이름이 있는 녀석은 세마포어를 만든 녀석과 그것을 공유하고 싶은 녀석끼리 별 관련 없을 때 사용하고, 이름 없는 녀석은 동일 프로세스 내 쓰레드끼리 또는 부모자식 같은 관계가 있을 경우에만 공유해서 사용하고 싶을 때 사용한다. 이름이 있냐 없냐 따라 생성 및 해체 API가 다르지만, 락을 걸고(값 감소), 푸는(값 증가) API는 동일하다.

먼저 이름이 있는 녀석부터 알아보자. 이름이 있는 녀석은 마치 세마포어 객체를 파일처럼 관리한다. 물론 정확히 파일은 아니므로, read/write/close 함수를 쓸 수 없다. 초기화는 sem_open 함수를 이용하며 형태는 아래와 같다.
sem_t* sem_open(const char* name, int oflag, mode_t mode, unsigned int value);

name은 이름 있는 녀석이므로 당연히 이름이 들어가야하고, 공유메모리처럼 '/'으로 시작하는 파일명을 써주는 것을 추천하는 바이다.

oflag는 열 때 어떤 방식으로 여는 가인데, O_CREAT, O_EXCL 말고는 쓸 일이 거의 없을 것 같다.

mode는 접근제어로 'S_'로 시작하는 매크로를 OR연산으로 묶어서 사용할 수 있다. 이것 역시 공유메모리 그것처럼 사용하는 것이다.

value는 세마포어 초기값을 설정할 때 사용한다.

당연한 이야기이겠지만, mode, value는 oflag에 O_CREAT를 설정해야만 의미가 있으며, man페이지에서 sem_open이 다른 모습으로 같이 소개하는 것도 있다. 뭐 이렇다~하는 정도만 알고 넘어 가자.

제대로 초기화를 끝내면 sem_t 포인터 형으로 세마포어 컨텍스트를 퉤!하고 뱉어준다. 물론 실패하면 NULL과 함께 그에 상응하면 errno를 세팅한다.

이렇게 만들어진 세마포어 객체는 sem_wait, sem_timedwait, sem_trywait 등을 통해 락을 걸고, sem_post를 통해 락을 푼다. 가용 락 개수는 sem_getvalue를 통해 얻을 수 있으며, 이것이 가지는 초기값은 sem_open에서 준 value와 동일하다.

잘 사용하고 더 이상 쓸 필요가 없는 세마포어 객체는 sem_close 함수를 통해 닫을 수 있지만, 없어지진 않는다. 파일과 마찬가지로 생성한 뒤에 닫는다고 파일이 없어지는 것이 아니듯, sem_unlink를 통해 세마포어 객체를 OS에 반환 신청을 해야한다. 물론 파일과 마찬가지로 반환신청했다고 바로 없어지는 것은 아니고, 해당 세마포어를 참조하는 프로세스가 모두 없어져야 비로소 세마포어 객체가 사라진다.

다음은 이름이 없는 세마포어. 이것 역시 이름 있는 녀석과 살짝 다르게 sem_t 객체를 미리 만들어놓고 시작해야한다. sem_t 라는 구조체 내부는 POSIX에서 정의하지 않았으며, 알 필요도 없다. 다만 사용범위에 따라 동일 프로세스 안에 쓰레드끼리 공유하는 객체로 사용하려면, 쓰레드끼리 같이 접근할 수 있는 메모리 영역(예를 들면 전역변수!)에 만들어야하며, 부모자식 프로세스끼리 공유하기 위해서는 semget+semat이나 shm_open+mmap으로 얻은 공유메모리에 만들지 않으면 원하는 결과를 얻을 수 없다. 이게 좀 귀찮다.

아무튼, 이름 없는 세마포어는 sem_open/sem_close 대신 sem_init/sem_destroy를 사용한다. sem_init은 다음과 같다.
int sem_init(sem_t* sem, int pshared, int value);

sem은사용범위에 따라 전역변수 또는 공유메모리에 선언한 변수 포인터이다.

pshared는 프로세스끼리 공유하는지 여부를 알려주는 플래그이며, sem을 전역변수 선언하여 쓰레드끼리만 쓰는 것이라면 '0'을, 그렇지 않고 부모자식 프로세스끼리 공유까지 열어주려면 '0' 이외 값으로 설정한다.

value는 sem_open에서 설명한 value와 동일하다. 세마포어 초기값이다.

논외지만, pshared라는 값을 지정해줘야 하는 까닭은 API 내부 입장에서 sem이 전역변수영역인지 공유메모리영역인지 모르며 또한 프로세스끼리 공유한다고 치면 sem_t 내부에 레퍼런스 카운터 같은 것이 있어 그것을 증감시켜야하기 때문이 아닐까 조심스레 
추측해본다. 아님 말고~ (딴따라당스러워~)

sem_destroy를 할 때는 반드시 락을 걸려고 시도하는 쓰레드가 없어야 한다. 또한 sem_destroy를 하지 않으면, 구현방식에 따라 메모리가 좔좔 샐 수도 있다고 하니 주의하도록 하자.

예제도 있으면 참 좋겠지만, 귀찮은 관계로 그냥그냥 넘어가자.


덧글: 살째기 재밌는 사실 하나 덧붙이자면, Linux2.6에서 sem_open하면 shm_open처럼 /dev/shm에 파일이 생긴다.
Posted by 삼스
임베디드/개발툴2009. 3. 2. 15:35

Are legacy objects and libraries compatible with my project?

Applies to: ARM Developer Suite (ADS)RealView Developer Kit (RVDK) for OKIRealView Developer Kit for XScale (RVXDK)RealView Developer Suite (RVDS) 2.0RealView Developer Suite (RVDS) 2.1RealView Developer Suite (RVDS) 2.2RealView Development Suite (RVDS) 3.0RealView Development Suite (RVDS) 3.1

ARM strongly recommends that you rebuild your entire project, including your own libraries and any libraries or code supplied by a third party using our most recent compilation tools. This allows you to take full advantage of the improved optimization, bug fixes and new features of the latest tools. There are some restrictions and potential incompatibilities if you build your project with legacy objects and libraries, for example, you may see the following error message:

Error: L6242E: Cannot link object foo.o as its attributes are incompatible with the image attributes.

This error can be avoided as described below.


http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0255hk/BABDGDGD.html


3.10. RVCT 버전 4.0과 레거시 객체 및 라이브러리와의 호환성

빌드 시 --apcs /adsabi를 사용하지 않았으며 RVCT 버전 4.0 링커와 C/C++ 라이브러리를 사용하는 경우 RVCT 버전 2.x 및 버전 3.x 객체/라이브러리 코드의 역방향 호환성이 지원됩니다. 정방향 호환성은 보장되지 않습니다.

이러한 제한 사항이 있으므로 사용자나 타사에서 제공하는 라이브러리를 비롯한 프로젝트 전체를 RVCT 버전 4.0으로 다시 빌드하는 것이 좋습니다. 이렇게 하면 비호환성을 방지하고 RVCT 버전 4.0에서 제공하는 개선된 최적화 기능, 향상 기능 및 새로운 기능을 모두 사용할 수 있습니다


http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/1347.html


Posted by 삼스
Linux2009. 2. 27. 13:49
1. 삼바서비스란?
SMB(Server Message Block) 프로토콜을 통해 지역 네트워크(LAN) 환경에서 UNIX-like 서버와 윈도우 클라이언트간에 파일이나 프린터간의 공유를 가능하게 해주는 패키지를 말한다. SMB는 OS/2, NT, WIN9x를 사용하는 컴퓨터끼리 파일 공유등의 서비스를 구현하는데 사용되는 프로토콜로 IBM PC와 MS의 윈도우가 DOS 3.0 이후부터 지속적으로 지원하고 있다. TCP/IP 기반하의 NetBIOS 프로토콜을 이용하기 때문에 이 프로토콜은 NFS, NIS, lpd 와 같은 유닉스의 분산인증구조와 유사하며 UNIX-like 시스템뿐 아니라 OpenVMS, OS/2, AmigaDOS, 그리고 Netware같은 다양한 플랫폼에서도 지원된다. 이것은 한가지 프로그램으로 프린터와 파일을 여러 플랫폼에서 손쉽게 공유할 수 있는 장점을 의미하는 것이다.

2. 구성요소와 기능
- 삼바는 서로 연관되어 있지만 약간씩 다른 목적으로 동작되는 몇 개의 프로그램들의 집합으로 이루어져 있다.
smbd : 삼바 서버와 클라이언트 사이의 공유된 리소스     를 운영하는 역활을 담당하는 데몬 프로그램. 네트워크를 통해 접근하는 클라이언트에 대해 파일, 프린터, 탐색 서비스를 제공한다. 그외 사용자 인증, SMB 프로토콜을 통한 데이타 공유, 리소스 락을 수행한다.
nmbd : WINS와 NetBIOS의 네임서버 기능을 모방하여 간단한 네임서비스를 제공하는 데몬이다. 이 외에 삼바는 다음 여러가지의 unix 명령어 툴들을 포함하고 있다.
smbclient: 공유되어 있는 삼바 디렉토리에 접근하는 유닉스 커맨드
smbtar : 공유되어 있는 디렉토리를 백업하기 위한 커맨드. tar과 비슷한 형태로 동작한다.
nmblookup: netbios네임서비스를 제공
smbadduser : 계정추가
smbpasswd : 비밀번호 설정
smbstatus : 현재 네트웤에 연결되어 있는 디렉토리 정보를 표시
testparm : 삼바설정파일(smb.conf)의 적합성을 테스트
testms : smbd에 의해 사용 가능한 프린테를 검색

 
3. 설정
/etc/samba에 설정내용이 있다. /etc/samba/smb.conf를 편집한다.

[global] 
# NT 도메인 네임, 또는 workgroup명. 윈도우에서 작업그룹에 해당된다. 
- workgroup = MYHOME 
# server string is the equivalent of the NT Description field 
- server string = My Samba Server 
# NetBIOS상에서 사용되어질 이름 
- ; netbios name = ns 
# utf-8로 인코딩된 한글파일명이 윈도우즈 시스템에서 잘 보이게 하기 
# 위해서는 다음과 같은 라인을 추가 또는 수정한다. 
- coding system = utf8 
- client code page = 949 
# 다른 별칭이 있을 때 사용 
- ; netbios aliases = ns 
# 액세스 허용 IP대역. 지정된 네트웍에서만 접근이 가능하도록 설정한다. 
- ; hosts allow = 192.168.1. 192.168.2. 127. 
# printcap에서 정의한 프린터 목록이 자동으로 등록되도록 하는 옵션 
- printcap name = /etc/printcap 
- load printers = no 
#프린터 시스템 지정옵션. 표준적인 프린터라면 주석을 풀 필요 없다. 
# bsd, sysv, plp, lprng, aix, hpux, qnx등의 프린터 시스템을 지원한다. 
- ; printing = lprng 
#guest 사용자를 허가하고 싶을 때 사용한다. 주석을 풀게 되면 이 값의 
#계정(여기서는 guest)이 /etc/passwd에 등록되도록 한다. 
- ; guest account = guest 
# 서버에 접속하는 호스트별로 로그파일을 만들도록 하는 옵션 
 #로그 사이즈는 KB 단위이다. 
- log file = /var/log/samba/%m.log 
- max log size = 0 
 #Security mode. 
 #share는 사용자 인증을 거치지 않고 자원에 접근할 수 있게 한다. 
- security = share 
 #한국어를 보기 위해 코드 페이지를 949로 설정한다. 
- client code page = 949 
#security 옵션에 server로 설정할 때 사용. 
- ; password server = <NT-Server-Name> 
- ; password level = 8 
- ; username level = 8 
# 패스워드를 암호화하고자할 때 사용. 
- encrypt passwords = yes 
- smb passwd file = /etc/samba/smbpasswd 
# 윈도우에서 패스워드를 바꿀 때 리눅스 시스템의 패스워드도 자동으로 
   갱신되도록 하고 싶을 때 사용한다. 
# 삼바 사용자와 계정 사용자가 일치하지 않을 경우 사용하는 것이 좋다. 
- unix password sync = Yes 
- passwd program = /usr/bin/passwd %u 
- passwd chat = *New*password* %n\n *Retype*new*password* %n\n *passwd:*all*authentication*tokens*updated*successfully* 
# You can use PAM's password change control flag for Samba. 
If  enabled, then PAM will be used for password changes when requested  by an SMB client instead of the program listed in passwd program.  It should be possible to enable this without changing your passwd  chat parameter for most setups. pam password change = yes 
 유닉스 사용자 이름과 smb 사용자 이름이 달라 둘 간이 map 테이블이 필요할 때 사용 ; username map = /etc/samba/smbusers 
# This parameter will control whether or not Samba should obey PAM's  account and session management directives. The default behavior is  to use PAM for clear text authentication only and to ignore any  account or session management. Note that Samba always ignores PAM  for authentication in the case of encrypt passwords = yes obey pam restrictions = yes 
다음 옵션을 주면 성능을 향상시킨다고 한다. 
- See speed.txt and the manual pages for details 
- socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192 
#삼바가 여러 인터페이스를 사용하도록 설정한다. 
- ; interfaces = 192.168.12.2/24 192.168.13.2/24 
# Configure remote browse list synchronisation here 
# request announcement to, or browse list sync from: 
 a specific host or from / to a whole subnet (see below) 
- ; remote browse sync = 192.168.3.25 192.168.5.255 # Cause this host to announce itself to local subnets here 
- ; remote announce = 192.168.1.255 192.168.2.44 # DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names # via DNS nslookups. The built-in default for versions 1.9.17 is yes, 
# this has been changed in version 1.9.18 to no. 
- dns proxy = no 
# DOS파일에서는 기본적으로 대문자를 쓴다. 
- ; default case = lower 


##
## 여기부터 공유설정
##

[homes] 
comment = Home Directories 
browseable = yes
writable = yes 
valid users = %S 
create mode = 0664 
directory mode = 0775 
invalid users = root

[yslee] 
comment = My folder 
path = /home/yslee 
valid users = yslee
public = no
writable = yes 
printable = no
read list =
write list =

yslee 계정 디렉토리의 사용자는 valid user에 적고 읽기 권한만 줄 유저는 read list에, 쓰기 권한을 줄 유저는 write list에 명시한다. 이때 각 유저는 ,로 구분하고 그룹의 경우에는 앞에 @를 붙인다. public은 공개적으로 사용되어질 디렉토리를 지정하고 모든 사용자가 함께 사용할 수 있으며 생성되는 모든 파이른 기본 소유자가 모든 사용자가 되므로 서로에 파일에 대하여 지울수도 있는 설정이다. 
이제 설정이 모두 끝났으나 위에서 적용한 삼바 유저와 패스워드를 설정하는 일이 남았다. 삼바 유저를 추가하는 것은 smbadduser 커맨드를 사용한다. 

[public] 
path = /home/public 
public = yes 
only guest = yes 
writable = yes 
printable = no


4. 사용자 설정

4.1사용자 추가
$smbadduser unix_id:nt_id 
  unix_id는 말 그대로 유닉스 계정명이고 nt_id는 NetBIOS 네임을 정해준다. 만약 삼바에 계정이 있고 패스워드만 바꾸고자 할 때는 smbpasswd를 사용한다.
$smbpasswd id 
  만약 비번없이 접근하기 위해서는 -n 옵션을 주면되는데 혼자쓸 때는 괜찮지만 여러 사용자가 공유하는 파일서버에는 권장하지 않는다.
  $smbpasswd -n username 

5. 공유디렉토리 접근
5.1 윈도우에서의 접근
  삼바 서버에서 공유한 디렉토리에 접근하기 위해선 네트워크 환경에서 직접 공유 디렉토리로 접근해도 되고 삼바 서버를 파일 서버로 이용하고자 한다면 바탕화면의 네트워크 환경 아이콘에서 오른쪽 클릭을 하면 '네트워크 드라이브 연결'이라는 메뉴가 있다. 이것을 선택해서 경로(P)라는 곳에 연결하고자 하는 시스템 이름(NetBIOS상의 이름)을 적고 그 뒤에 연결하고자 하는 디렉토리를 설정한다. 시스템의 재시작 후에도 항상 연결하여 사용하려면 '로그온할 때 다시 연결(T)' 메뉴에 체크해 두면 된다. 이후 사용자 암호를 묻는 창이 뜨고 거기에 삼바 설정시 설정해둔 삼바 암호를 입력하면 삼바 서버로의 네트워크 드라이브 연결이 끝나게 된다. 직접 공유 디렉토리로 접근하기 위해선 시작 -> 실행 을 선택해서 다음의 커맨드로 접근할 수 있다. 
  \\삼바서버IP\
5.2 리눅스에서 윈도우에 접근
  리눅스에서 윈도우 공유 폴더에 접근하려면 먼저 해당 컴퓨터의 공유 폴더에 어떤 것들이 있는지 알아야 한다. 이러한 공유자원을 알아보는 명령이 smbclient 이다

smbclient -L 컴퓨터이름 <-- 로칼 네트워크에 있는 컴퓨터일 경우 smbclient -L 컴퓨터이름 -I 컴퓨터의 IP주소 <-- 외부 네트워크에 있는 컴퓨터일 경우 
예) 
$smbclient -L choco 
$smbclient -L choco -I 100.200.100.200 

이제 공유 폴더에 접근하기 위한 커맨드를 내려보자.

smbclient //컴퓨터이름/공유이름 
smbclient //컴퓨터이름/공유이름 -I 컴퓨터의 IP주소 
예) 
$smbclient //착한동우/temp -I 100.200.100.200 

공유 폴더를 마운트 하기 위해선 smbmount를 사용한다. 
smbmount //컴퓨터이름/공유이름 마운트할디렉토리 
mount -t smbfs //컴퓨터이름/공유이름 마운트할디렉토리 
예) 
$mount -t smbfs //착한동우/temp /mnt/samba

6. 삼바서버 구동
6.1 standalone방식
  삼바를 구동시키기 위해선 위에서 설명한 바와 같이 삼바 서버(smbd)와 netbios 네임서버(nmbd)를 띄워야 한다. 레드햇 배포판을 기준으로 설명하면 대부분의 stand-alone 데몬은 /etc/rc.d/init.d 디렉토리에 실행 스크립트가 설치되어 있다. 삼바 데몬 시작 스크립트인 smb또한 여기에 있다. 
  $/etc/rc.d/init.d/smb [stop:start:restart] 간편하게 service 유틸로 데몬을 제어하기도 한다. 
  $service smb [stop:start:restart] 부팅할 때마다 삼바를 자동우로 구동시키기 위해선 /etc/rc.d/rc.local 파일에 다음을 기술한다.

usr/local/samba/bin/smbd -D /usr/local/samba/bin/nmbd -D

6.2 inetd방식
  삼바 데몬도 inetd 수퍼데몬을 통해 간접적으로 띄울 수 있다. stand-alone 방식보다는 아무래 반응시간이 약간 길게 느껴질지 모르지만 요즘처럼 빠른 컴퓨팅 환경에서는 사실 눈에 띄는 저하는 아닐 것이다. inetd 방식의 데몬은 데몬이 제공하는 서비스를 사용하지 않을 경우 관련 서버 데몬들이 프로세스로 떠 있지 않기 때문에 시스템 자원을 그만큼 덜 차지하는 효과가 있다. 삼바도 SMB 요청이 들어올 때만 inetd에 의해 데몬이 구동된다.
대부분의 inetd 방식의 데몬 실행 방법과 동일하다. 먼저 /etc/service 파일에 서비스 정의 구문을 적어주고 /etc/inetd.conf에 데몬 실행 명령을 적어주면 된다. 

/etc/service 파일에 다음의 내용이 있는지 확인하고 없으면 추가한다. netbios-ns 137/tcp nbns 
netbios-ns 137/udp nbns 
netbios-dgm 138/tcp nbdgm 
netbios-dgm 138/udp nbdgm 
netbios-ssn 139/tcp nbssn 
/etc/inetd.conf에 다음의 내용을 확인한다.
netbios-ssn stream tcp nowait root /usr/sbin/smbd smbd netbios-ns dgram udp wait root /usr/sbin/nmbd nmbd 


"네트워크 경로를 찾지 못했습니다."라는 오류 발생시
일단 공유 설정에서 공유 디렉토리 경로가 제대로 지정되어 있는지 확인하고 이상이 없다면 방화벽이 접근을 막고 있을 공산이 크다. setup을 실행해서 Firewall Configuration을 No firewall로 설정하라. 그리고 윈도우 클라이언트에서 시작 -> 실행 -> 열기란에 \\리눅스호스트명으로 접근해보라. iptables나 ipchains가 작동중이라면 -F 옵션을 주어서 방화벽 구동을 중지시켜 본다. $ipchains -F 이렇게 했는데 로칼 LAN에서는 접근이 잘 되고 다른 망으로 넘어가면 역시 "네트워크 경로를 찾지 못했습니다."라는 메시지가 나오면서 접근이 되지 않는다면 삼바 서버의 자체 문제가 아니라 네트워크단에서 NetBIOS를 막고 있는 것이다. 보통 대부분의 회사나 학교에서는 NetBIOS 패킷들을 필터링하는 정책을 쓰고 있는데 이는 많은 웜이나 바이러스가 네트웍 공유를 통해서 전파되기 때문이다. 네트워크 관리자에게 문의를 해보면 아마 금방 알 수 있을 것이다. 

Posted by 삼스