* First of all, check your kernel configuration.

- CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y    <- Optional

* Create your Kernel module code and Makefile


If you have luck, everything should be OK. But...


CASE: error at insmod?

insmod: init_module 'hello.ko' failed (Exec format error) in android
kernel message : unknown relocation: 27
Hmm, then you should check kernel functions you are using in the module (ex. printk)
You can check relocation type with following command (ex. printk)

readelf -r hello.ko | grep prink

Then, result may like below

xxxxxxxx  xxxxxxxx R_ARM_PLT32       00000000   printk

For your information : number 27 indicates R_ARM_PLT32.

Then, what's the problem?
ELF for the ARM Architecture(IHI0044E_aaelf.pdf) says that R_ARM_PLT32 is deprecated.
And, Linux kernel doesn't handle R_ARM_PLT32 at module.c : apply_relocation() function
We have two workaround for this issue.

* Update toolchains.
In my case, I faced this issue when I used gcc-4.4.3. And, gcc-4.7 resolved this issue.
(You can see, relocation type is changed into R_ARM_CALL instead of R_ARM_PLT32.)

* fpic / fno-pic HACK.
If you are in trouble with upgrading your toolchains, here is workaround (tested on gcc-4.4.3).
Add, -fpic or -fno-pic at CFLAGS_MODULE in your module Makefile like below.

make CFLAGS_MODULE=-fpic xxxx modules

Then, like above - updating toolchains -, relocation type is changed :-)



Java에서는 selective compile이 되지 않는다.

대신, compile time에 결정되는 것들을 이용해서 selective compile과 비슷한 효과를  만들어 낼 수 있다.

예를 들면,


Config.jar
----------
class Config {
...
    public static final boolean DEBUG = false;
...
}


Main.java
---------
...
if (Config.DEBUG) System.out.println("debug line...");
...

자, 그러면 어디서 어디까지 Compile time 에 결정되는가?

openJDK 1.6에서 test를 해 보면, 아래의 것들에 대해서는 compile time에 결정되는다는 것을 확인했다.


primitive types (int, boolean, long...) + String.


여기서 의외의 부분이 'String'인데...

실제, 아래와 같이 static final String 변수로 test해 보면, 이것을 확인할 수 있다.

Config.jar
----------
class Config {
    ...
    public static final String MODE = "debug";
    ...
}


Main.java
---------
...
if (Config.MODE.equals("debug")) System.out.println("debug mode...");
...

생각해보면, String class자체가 constant class이므로 - 한번 생성되면, 내용이 바뀌지 않는 class - 위와 같은 compile time check가 가능하지 않을까... 생각이 든다.


아래는 위의 내용에 대한 상세 test이다.

test/lib/Config.java -------------------- package test.lib; public class Config { public static final int TEST_INT_0 = 1; public static final boolean TEST_BOOL_0 = false; public static final String TEST_STR_0 = "test-str-0"; public static int TESTV_INT_0 = 1; public static boolean TESTV_BOOL_0 = false; public static String TESTV_STR_0 = "test-str-0"; } ===> export to 'test0.jar' package test.lib; public class Config { public static final int TEST_INT_0 = 10; public static final boolean TEST_BOOL_0 = true; public static final String TEST_STR_0 = "test-str-1"; public static int TESTV_INT_0 = 10; public static boolean TESTV_BOOL_0 = true; public static String TESTV_STR_0 = "test-str-1"; } ===> export to 'test1'jar Main.java ---------- import test.lib.Config; public class Main { public static void main(String[] args) { if (Config.TEST_STR_0.equals("test-str-0")) System.out.println("Config:TEST_STR_0 : IF path - test-str-0"); else System.out.println("Config:TEST_STR_0 : ELSE path - test-str-0"); if (Config.TEST_INT_0 > 5) System.out.println("Config:TEST_INT_0 : IF path - > 5"); else System.out.println("Config:TEST_INT_0 : ELSE path - > 5"); if (Config.TEST_BOOL_0) System.out.println("Config:TEST_BOOL_0 : IF path - true"); else System.out.println("Config:TEST_BOOL_0 : ELSE path - "); if (Config.TESTV_STR_0.equals("test-str-0")) System.out.println("Config:TESTV_STR_0 : IF path - test-str-0"); else System.out.println("Config:TESTV_STR_0 : ELSE path - test-str-0"); if (Config.TESTV_INT_0 > 5) System.out.println("Config:TESTV_INT_0 : IF path - > 5"); else System.out.println("Config:TESTV_INT_0 : ELSE path - > 5"); if (Config.TESTV_BOOL_0) System.out.println("Config:TESTV_BOOL_0 : IF path - true"); else System.out.println("Config:TESTV_BOOL_0 : ELSE path - "); } } ========================================== $ javac -classpath test0.jar Main.java $ java -classpath .:test0.jar Main Config:TEST_STR_0 : IF path - test-str-0 Config:TEST_INT_0 : ELSE path - > 5 Config:TEST_BOOL_0 : ELSE path - true Config:TESTV_STR_0 : IF path - test-str-0 Config:TESTV_INT_0 : ELSE path - > 5 Config:TESTV_BOOL_0 : ELSE path - true $ $ java -classpath .:test1.jar Main Config:TEST_STR_0 : IF path - test-str-0 <--- 바뀌지 않음. (변수 값이 compile time에 이미 binding되어 있음.) Config:TEST_INT_0 : ELSE path - > 5 <--- 상동 Config:TEST_BOOL_0 : ELSE path - true <--- 상동 Config:TESTV_STR_0 : ELSE path - test-str-0 Config:TESTV_INT_0 : IF path - > 5 Config:TESTV_BOOL_0 : IF path - 참고 : TESTV_XXX_0를 없애면, test0.jar 혹은 test1. jar를 'java'의 'classpath' 에 명시해 주지 않더라도 정상수행 된다. ex. $ java Main 왜냐하면, 이미 모든 code가 compile time에 binding어 있는 상태으므로, Runtime에는 더 이상 'test.lib.Config' 를 참조하지 않기 때문이다.

위와 같은 static final 변수를 runtime binding하기 위한 방법의 한 예로 reflection을 들 수 있다.

reflection을 이용해서 해당 변수 field를 접근하면, static final로 선언된 변수이지만, runtime binding이 가능하다.

일단 man page를 유심히 살펴보자.

FIFO(7)                             Linux Programmer's Manual                            FIFO(7)

NAME
       fifo - first-in first-out special file, named pipe

DESCRIPTION
       A  FIFO  special  file (a named pipe) is similar to a pipe, except that it is accessed as
       part of the file system.  It can be opened by multiple processes for reading or  writing.
       When  processes  are  exchanging data via the FIFO, the kernel passes all data internally
       without writing it to the file system.  Thus, the FIFO special file has  no  contents  on
       the  file  system;  the file system entry merely serves as a reference point so that pro‐
       cesses can access the pipe using a name in the file system.

       The kernel maintains exactly one pipe object for each FIFO special file that is opened by
       at  least one process.  The FIFO must be opened on both ends (reading and writing) before
       data can be passed.  Normally, opening the FIFO blocks until  the  other  end  is  opened
       also.

       A  process can open a FIFO in nonblocking mode.  In this case, opening for read only will
       succeed even if no-one has opened on the write side yet, opening for write only will fail
       with ENXIO (no such device or address) unless the other end has already been opened.

       Under  Linux,  opening  a  FIFO for read and write will succeed both in blocking and non‐
       blocking mode.  POSIX leaves this behavior undefined.  This can be used to  open  a  FIFO
       for  writing  while there are no readers available.  A process that uses both ends of the
       connection in order to communicate with itself should be very careful to avoid deadlocks.

NOTES
       When a process tries to write to a FIFO that is not opened for read on  the  other  side,
       the process is sent a SIGPIPE signal.

       FIFO  special files can be created by mkfifo(3), and are indicated by ls -l with the file
       type 'p'.

SEE ALSO
       mkfifo(1), open(2), pipe(2), sigaction(2), signal(2), socketpair(2), mkfifo(3), pipe(7)

COLOPHON
       This page is part of release 3.35 of the Linux man-pages project.  A description  of  the
       project, and information about reporting bugs, can be found at http://man7.org/linux/man-
       pages/.

Linux                                      2008-12-03                                    FIFO(7)

주의할 사항은 위에서, Bold로 표시해 두었다.


먼저 "read/write 양쪽이 열리기 전까지는 open이 block된다."는 말이 무슨 말일까?

아래 코드를 살펴보자.

int main()
{
	char msg[64];
	int fd;
	int rd;

	if (-1 == mkfifo("./fifo",0666))
		return 1;

	if (-1 == (fd = open("./fifo", O_RDWR))) // <--- (*A)
		return -1;
	printf("Before loop\n"); // <--- (*a)
	for (;;) {
		if (-1 == (rd = read(fd, msg, sizeof(msg))))
			return 1;
	}
	unlink("./fifo");
	return 0;
}

위의 코드는 실행시키면 바로 , (*a)가 수행된다.

그렇지만, (*A)의 open mode를 O_WRONLY 나 O_RDONLY 로 하면, pipe의 다른 한쪽 (read 혹은 write)가 열리기 전까지는 (*a)가 수행되지 않는다 (open에서 block된 상태) 는 말이다.



그리고, "read only의 경우 nonblocking mode로 open이 가능하다고 wirte는 안된다." 는 어떤식 문제를 가져 오는가?

앞서 이야기한 것처럼, 위의 코드에서, (*A)를 O_RDONLY로 하면, write pipe가 열리기 전까지는 (*a)가 수행되지 않는다.(block된 상태).

그렇지만, "$ echo hello > ./fifo" 같은 명령을 통해 write side를 일단 열개 되면, loop로 들어가게 되는데,

문제는, read가 NONBLOCKING으로 동작한다는 것이다.

즉, 더 이상 읽을 것이 없음에도 불구하고, block이 되지 않고 busy loop를 돌게 된다.
하지만, 위의 예시처럼, O_RDWR로 열게 되면, 더 이상 읽을게 없을 경우, read 에서 block 되어, 일반적으로 기대하는 방식으로 동작하게 된다.


추가적으로, File이란, System-wide한 resource이다.

따라서, 두 개 이상의 Process가 하나의 Pipe에 대해 동시에 read를 하고 있다면, 먼저 읽는 Process가 Pipe의 내용을 읽어가게 되고, 다른  Process들은 내용을 읽지 못한다.


'Language > C&C++' 카테고리의 다른 글

'malloc' and 'Segmentation fault'  (0) 2014.07.25
[GCC] Initialize array...  (0) 2014.07.25
[c/c++] file copy using 'sendfile' on linux.  (0) 2013.12.17
일반 file에 대한 select/poll...  (0) 2013.11.14
Using allocated memory like 2-D array.  (0) 2013.07.10

회사 생활을 하다보면 제목과 같은 말을 듣는 경우가 종종 있다.

실무 선에서의 문제가 첨예한 의견대립으로 상위선까지 번지게 되는 경우가 있는데, 이런 문제가 자주 나타나게 될때, 상급자들이 하는 대표적인 말 중 하나일 것이다.


"왠만하면, 실무선에서 해결하라. 그런 문제를 해결하는 것 또한 실무 능력이다." 의 의미를 내포한다고 볼 수 있다.

분명, 이러한 의견대립을 잘 해결하는 것 엮시 실무 능력의 중요한 요소 중 하나이다.

너무 많은 의견 대립이 생기고, 상급자(관리자)가 관여해야 할 문제들이 너무 자주 발생한다면, 실무자의 업무 능력이나 태도에 대한 세밀한 관찰이 필요한 것도 사실이다.

그렇지만, 그 부작용 또한 만만치 않다.


예를 들어, A팀 실무자와 B팀 실무자가 서로 협력해서 일해야 하는 경우를 가정해보자.

R&R이 아무리 잘 나뉘어져 있더라도 모호한 부분은 항상 있게 마련이고, 이런 부분에 대한 처리 문제로 의견이 대립하는 경우가 엮시 종종 발생하게 된다. 혹은, 극단적으로는 한쪽에서 다른 쪽으로 너무 무리한 요구를 계속해서 하는 경우도 있을 수 있을 것이다.

이때, A팀 팀장은 실무자를 적극적으로 support하고 있고, B팀 팀장은 실무자에게 '제목'과 같은 이야기를 했다고 가정해보자.

자... 어찌 되겠는가?

B팀 실무자가 A팀 실무자로부터 무리한 요구를 받거나, 혹은 R&R에서 벗어난 요구를 받았을때 - 물론, A팀 실무자는 이것이 무리한 요구라고 생각하지 않을 것이다. 입장차이가 존재하므로... - B팀 실무자가 이를 거부한다면, A팀 실무자는 팀장의 도움을 요청할 것이고, A팀 팀장은 실무자를 적극적으로 support할 의사가 있으므로, B팀 팀장에게 업무 협조 요청을 할 것이다.

자, 이제 B팀 팀장은 실무자에게 상황을 보고 받고, 판단에 따라 '수락' 혹은 '거부' 의사를 전할 것이고, 실무자에게는 질책과 함께, '제목'과 같은 지시를 다시금 전할 것이다.

위와 같은 일이 몇차례 반복되면, B팀 실무자는, 의견대립으로 인해 A팀 팀장이 나서서 B팀 팀장과 연락하게 되는 것에 대한 거부감(혹은 두려움)이 생기게 마련이고, 정말 심하게 무리한 요구가 아니라면 왠만하면 '의견대립'에서 A팀의 요구를 받아 들이는 방향으로 결정하게 될 것이다. 왜냐하면, 그래야만이 관련 문제가 팀장에게까지 전달되는 것을 막을 수 있기 때문이다. 그와 함께, 이러한 "의견 대립"도 줄어 들게 된다.


자... 그럼 결과적으로 어떤 그림이 그려지는가?

관련 일에 대한 의견 대립이 줄어들었으므로, 이에 대한 상급자의 평가는 두 실무자 모두에게 같은 정도의 "이익"으로 돌아가게 된다.(혹은 그 동안의 의견 대립에 대해서 같은 정도로 "피해"가 갈 수도 있겠다.)

하지만, A팀 실무자는 R&R이 명확한 본인의 일만을 처리하면 되므로 업무의 부하가 줄어들게 되는 반면, B팀 실무자는 본인 업무 + R&R이 불명확한 기타 업무 까지 해야하게 되므로 업무 부하가 늘어나게 된다.

두 실무자의 역량이 같다고 가정하면, A팀 실무자는 같은 일을 적은 업무 부하로 해결하고 있으므로 뛰어난 성과를 보일 것이고, B팀 실무자는 반대의 상황에 놓이게 될 것이다.


여기서 필자가 하고 싶은 말은, 팀장이 잠깐 고생하면, 팀원의 업무부하를 상당량 줄여줄 수 있고, 그것은 곳 팀의 업무 성과로 연결된다는 것이다.

반면, 팀장이 어떠한 이유가 되었건 - 귀찮아서, 아니면 본인이 바빠서, 기타 등등 - 위와같은 태도를 취하게 되면, 팀원의 업무 만족도 및 성과는 떨어지게 되고, 그 피해는 결국 팀장 자신에 돌아오게 된다.

어떤 팀의 팀원들이, 협력상대가 되는 팀에 비해 전반적으로 모두 업무 부하가 심하고, 업무성과가 저조하다면, 팀장이 위와 같은 태도를 취하고 있는 것은 아닌지 한번쯤 확인해 볼 필요도 있어 보인다.


+ Recent posts