[ related information ]
* prctl
* See linux kerne for details ("kernel/exit.c : find_new_reaper())

------ commit(kernel/git/torvalds/linux.git) -----
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ebec18a6d3aa1e7d84aab16225e87fd25170ec2b

author	  Lennart Poettering <lennart@poettering.net>    2012-03-23 22:01:54 (GMT)
committer Linus Torvalds <torvalds@linux-foundation.org> 2012-03-23 23:58:32 (GMT)
commit	  ebec18a6d3aa1e7d84aab16225e87fd25170ec2b (patch)




=====================================================================
[ test code ]
-------------

$ cat b.sh
function echosleep2 {
    sleep 10
    echo 'sleep2 end'
}


function echosleep {
    echosleep2&
    sleep 5
    echo 'sleep end'
}

echo "hello: $BASHPID $$"
echosleep&
sleep 2
echo end
=====================================================================




=====================================================================
[common]
--------

  PID  PPID  PGID   SID CMD
 3241  2573  3241  3241 init --user
 ...
 4392  3241  3374  3374 gnome-terminal
 ...
 9882  4392  9882  9882 bash
 ...
=====================================================================



=====================================================================
[ < 2 seconds ]
---------------

  PID  PPID  PGID   SID CMD
33513  9882 33513  9882 bash            # ./b.sh (*a)
33514 33513 33513  9882 bash            # ./b.sh:echosleep() (*b)
33515 33513 33513  9882 sleep 2
33516 33514 33513  9882 bash            # ./b.sh:echosleep():echosleep2() (*c)
33517 33514 33513  9882 sleep 5
33518 33516 33513  9882 sleep 10
33519 15742 33519 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

(*a): Bash terminal executed 'b.sh' as new process group leader.
      All child/grandchild processes are executed in the same process group.
=====================================================================




=====================================================================
[ < 5 seconds ]
---------------

  PID  PPID  PGID   SID CMD
33514  3241 33513  9882 bash            # ./b.sh:echosleep() (*b)
33516 33514 33513  9882 bash            # ./b.sh:echosleep():echosleep2() (*c)
33517 33514 33513  9882 sleep 5
33518 33516 33513  9882 sleep 10
33520 15742 33520 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

(*b): Process group leader(*a) is disappeared.
      And there is no threads in this process.
      (If there is other threads in this process, it will become new reaper)
      So, it is re-parented to orphan-reaper("init --user").
=====================================================================



=====================================================================
[ < 10 seconds ]
----------------

  PID  PPID  PGID   SID CMD
33516  3241 33513  9882 bash            # ./b.sh:echosleep():echosleep2() (*c)
33518 33516 33513  9882 sleep 10
33522 15742 33522 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

(*c): Same with above(*b).
=====================================================================



=====================================================================
[ > 10 seconds ]
----------------

  PID  PPID  PGID   SID CMD
33524 15742 33524 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

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


Sample code to get every SIGCHLD from descendents.
---------------------------------------------------


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <errno.h>

void handle_signal(int signal) {
        pid_t pid;
        printf("Handler SIGCHLD: %d\n", signal);
        if (0 > (pid = wait(NULL))) {
		printf("Wait fails: errno: %s", strerror(errno));
	} else {
		printf("Wait done: %d\n", pid);
	}
}

int main() {
        struct sigaction sa;
	pid_t pid;

        // Print pid, so that we can send signals from other shells
        printf("My pid is: %d\n", getpid());

        // Setup the sighub handler
        sa.sa_handler = &handle_signal;

        // Intercept SIGHUP and SIGINT
        if (sigaction(SIGCHLD, &sa, NULL) == -1) {
                perror("Error: cannot handle SIGCHLD"); // Should not happen
        }

        if (0 > prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)) {
                perror("Error: prctl");
        }

	pid = fork();
	if (pid) {
		int secs = 10;
		// parent
		printf("\nSleeping for 10 second\n");
		while (secs > 0)
			secs = sleep(10);
		printf("Parent DONE\n");
	} else {
		// child
		if (0 > execlp("bash", "bash", "b.sh", NULL)) {
			printf("execl fails: %s\n", strerror(errno));
		}
	}
}




'Ninja' has implicit dependency on input '.ninja' file.

Let's thing about following example.


< build.ninja >


rule hello

     command = echo ${msg}


build aaaa: hello

      msg = aaaa


build build.ninja: hello

      msg = build.ninja


-----


$ ninja yyyyyyy

[1/1] echo build.ninja

build.ninja

ninja: error: unknown target 'yyyyyyy'



---------------



Ninja try to build input '.ninja' file if rule for the '.ninja' is defined.

And then Ninja try to build given target.


Software개발이란, 사람의 편의를 도와주는 도구를 만드는 것과 밀접한 관련이 있다.

그리고, 이런 류의 도구들은 생산성 향상을 가져온다.


SW 엔지니어의 경우, 특히나, 수많은 소위 'Manual'한 작업들을 SW개발을 통해서 'Automation'을 하는 과정을 중요시 한다.

왜냐하면, 단순한 작업을 최소화함으로서 더 많은 시간을 '창조적인 작업'에 사용하길 원하기 때문이다.

그러나, 국내에서는 SW개발을 '창조적인 작업'으로 생각하지 않는 곳이 많다.

(여기에 대한 논란은 접어두자. 국내에서, SI와 Game쪽을 제외하고 SW가, 수익의 중심에 있는 산업은 거의 전무하다. Portal쪽은 '업계'라고 표현하기 어렵다. 대표적인 기업 2개 정도만 존재하니...)

그러다보니, 자동화나 Tool 등을 통해 기존 업무의 생산성을 향상시키면 (예를 들어, 기존 10여명이 필요한 일을 1~2명이 할 수 있게 했다면) 당해년도, 그러니까, 생산성을 향상시킨 그 해에는 좋은 평가를 받을 수 있게 되나, 그 이후에는 나머지 사람들은 소위 '할일이 없게' 된다.

즉, 다시 무언가 성과를 낼 새로운 일을 찾지 못하면, 그 이후 부터는, '나쁜' 평가를 받게 된다.


그리고, 대부분의 경우, 새로운 일을 찾는 것은 상당히 어렵기 때문에, 여유있는 사람들은, 그때 당시 업무가 과중하게 몰리는 다른 부서 혹은 분야 쪽을 투입되는 경우가 많다. 그렇게 되면, 업무가 바뀌게 되면, 대부분의 사람들이 그렇듯이, 그 사람은 새로운 환경 그리고 업무 domain에 적응해야 하고, 초반 상당기간은 '좋은 성과'를 보여주기 힘들다.


예를 들어, 대략 정리해 보자.

- 10여명의 SW 엔지니어로 구성된 team이 있다.

- 해당 team은 반복적이고 routine한 업무를 지속적으로 수행하고 있고, 이 업무는 회사내에 필수적이며, 10여명이 꾸준히 해 나가야 하는 일이다.

- 이 업무는 Automation이나, 기타 방법으로 생산성을 향상시키기가 상당히 어렵다.


Case A: 해당 업무를 지속한다. 약간씩의 improvement는 꾸준히 진행한다.

- 기본적으로 필요한 일을 지속하고 있으므로, '좋은 실적'을 보여준다고 말할 수는 없어도 '나쁜 실적'을 보여주지도 않는다. 그냥 '평이한' 평가를 일정기간 계속해서 받을 가능성이 높다.

- 해당 일에 대한 생산성 향상이 상당히 어렵다는 것이 이미 알려진 사실이므로, 약간씩의 improvement를 통해 추가적인 실적을 보여주면서 '좋은 평가'를 노려 볼수 있다.

- 해당 team은, 이미 익숙한 사람/동료/업무 환경속에서 생활하므로 관련 스트레스도 크지 않다.

- 업무에 대한 비젼이 약하므로, 이 부분에 불만이 생길 여지가 있다.


Case B: 창의적인 생각과 노력으로 생산성 향상에 성공한 경우 (필요 인력: 10여명 -> 1~2명)

- 해당 년도에 '좋은 성과'를 받을 가능성이 높다.

- 이후, 8~9 명은 당장 인력이 부족한 팀/업무 쪽으로 재배치되고, 나머지 1~2명 역시 다른 팀으로 이동될 가능성이 높다.(1~2명이 독립적인 팀으로 유지될 수는 없다.)

- 1~2 명은 생산성 향상을 가져온 새로운 환경에서, 창조적인 생각/업무 를 할 수 있는 여력이 없이 빠듯하게 기존 업무를 계속해서 수행해 나갈 것이다.

- 재배치된 8~9명은 새로운 환경/업무에 적응하면서 초반에는 '좋지 못한' 평가를 받을 가능성이 높다.


Case B 의 경우, 해당 팀의 leader는 좋은 평가와 함께, 이후에도 더 좋은 기회를 얻게 될 가능성이 있다. 그렇지만, 팀원들은 어떤가?

B의 경우를 경험해 본 사람은, 다시 이와 비슷한 상황에서, 생산성 향상/자동화 등에 강한 거부감을 가지게 된다.

(나는 실제, 이런 상황을 경험해 보았고, 대부분의 팀원은 앞서 말한대로, 이후 생산성 향상/자동화 등에 거부감을 가지게 되었다.)


생산성을 향상시키기 위한 업무에 성공한 팀/사람 이 긍적적인 결과를 경험했을때, 이후 같은 상황에서도 이를 위해 노력할 것이다. 그런데, 과연 우리 주변의 환경은 어떤가?

내가 보기에는 그리 긍정적이지 않아 보인다...

제목 그대로다.

"멤버가 하고 있는 일, 노력 그리고 성과 등을 정확하게 파악하는 일"은 관리자가 해야할 일 중요한 일 중 하나이다.

왜냐하면, 멤버의 성과를 결국 평가해야하기 때문이다.

그렇지만, 그것만큼 중요한 건 "멤버들이, 내가 관리받고 있고, 관리자가, 나의 일, 성과 그리고 노력을 정확하게 파악하고 있다."라고 인식하게 하는 것이다.

사실 실제로 관리자가 "얼마나 '정확히' 파악하고 있나?"와는 별개로, 멤버들이 "자신들이 관리받고 있다."라고 느끼고 있다면, 나태해 지지 않고, 또 자신의 성과를 터무니없이 과장하는 등의 문제도 줄어들게 된다.


물론 관리자의 가장 중요한 역할은 "팀원들이 자신의 업무/생활에 만족하면서, 팀 전체가 최상의 성과를 낼 수 있도록 이끌어 가는 것."이라는데는 변함이 없다.

Linux Kernel 3.10을 기준으로 보면,

Maximum number of environment variable in Linux : 0x7fffffff

Maximum string length of environment variable and argument: PAGE_SIZE * 32 (4K page의 경우 128K)


헛갈리기 쉬운 것 (용어를 명확하게 사용하고 있지 않은 것들.)

"environment variable" vs "shell variable"

 

Bash 기준으로 보면

 

export var=hello  # This is environment variable

var=hello   # This is shell variable.


즉, environment variable 이란 descendent process들에게 영향을 미치는 '환경'을 의미한다. Current process에서만 유효한 것은 environment variable이라 부를 수 없다.

추가적으로, '$ env' command를 수행할 때 나오는 값들 역시 environment variable만 나오고 shell variable은 나오지 않는다.


Here is the way to compile x86 goldfish and run on emulator


* AOSP Marshmallow + Goldfish 3.4

* ARCH=x86 (You don't need to set SUBARCH)

* Compiler version : gcc-4.8 (prebuilt x86 compiler from Android NDK)

  (Set CROSS_COMPILE environment variable)


$ make ARCH=x86 CC="${CROSS_COMPILE}gcc -mno-android" goldfish_defconfig

$ make ARCH=x86 CC="${CROSS_COMPILE}gcc -mno-android" -j40


And use 'arch/x86/boot/bzImage' as 'kernel-qemu' image


Please note that you SHOULD use '-mno-android' option to build linux kernel with NDK toolchains.
The reason is, '-mandroid' option is enabled by default at GCC in NDK(file name is something like *-*-android*)
Remember that NDK toolchain is used to build native executable or libraries run on Android devices.
And, in general, build environment of linux kernel is 'GCC' + 'GLIBC'.
(Note that, linux kernel binary even if it runs on Android device, it doesn't have any dependency on Android platform(ex. bionic or libc))
So, to build linux kernel, '-mandroid' option should be disabled by using '-mno-android' option.


StackOverlow 의 아래 답변을 참고하자.

http://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java


정리하면, JVM은 main thread가 끝나더라도, 아직 수행중인 다른 thread - non daemon thread(user thread) - 가 있다면, 중지되지 않는다.

즉, process가 계속해서 돈다.

C/C++ 처럼, main thread가 exit될 때 process를 종료시키려면, 모든 child thread 속성을 daemon thread로 설정해야 한다.


Thread t = new Thread(...)

t.setDaemon(true);


남아 있는 모든 thread가 Daemon thread일 경우, JVM은 중지된다.

다만, 이런식으로 thread가 급작스레 종료하는 것은 상당히 불안정한 결과를 가져 올 수 있으므로 주의해야 한다.


다시 말하면, 단 하나라도 종료되지 않은 user thread (non-daemon thread) 가 존재할 경우, JVM은 종료되지 않고, 모든 다른 thread (Daemon thraed 포함)역시 계속해도 수행된다.



In general, main function is used as below.


int main(int argc, const char *argv[]) {

}


But, it can be expanded like below


int main(int argc, const char *argv[], const char **envp) {

        while (*envp) {

                printf("%s\n", *envp++);

        }

}


By this way, we can use environment variables easily.

=> This matches parameters of execle() and execvpe() at Linux.



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

[C/C++] __attribute__((constructor)) and variable initialization in C++.  (0) 2024.01.23
[C/C++] Template with value  (0) 2015.04.28
[C/C++] sizeof array  (0) 2015.03.19
[Macro] '##' macro operator  (0) 2015.02.11
'malloc' and 'Segmentation fault'  (0) 2014.07.25

GNUMake document says

"An argument that contains ‘=’ specifies the value of a variable: ‘v=x’ sets the value of the variable v to x. If you specify a value in this way, all ordinary assignments of the same variable in the makefile are ignored; we say they have been overridden by the command line argument"


This means, value defined as command-line argument has top priority in terms of variable definition.


< Make file >

PRIV_V=hello_OUT

$(info $(PRIV_V))


all: a b

@echo all


a: PRIV_V := hello_A

a:

@echo $(PRIV_V)


b: PRIV_V := hello_B

b:

@echo $(PRIV_V)




< Test >

$ export PRIV_V=ENV

$ make

hello_OUT

hello_A

hello_B

all


$ make PRIV_V=CMD

CMD

CMD

CMD

all


* Tips : Variable definition in gnumake command line.

Variable definition syntax in the Makefile, is also available as command line argument.

Example.

$ make CC=Hello

$ make CC:=Hello

$ make CC+=Hello

function 을 define하는 시점에 default value를 binding한다.

(Spec.을 찾아본건 아니고.. 시험적으로...)



[test.py]


_DEFVAL = 10


def set_def(val):

    global _DEFVAL

    _DEFVAL = val


def prdef(val=_DEFVAL):

    print '+++ ' + str(val) + '\n'


prdef()

set_def(0)

prdef()


============== outputs ==============

+++ 10


+++ 10


'Language > Python' 카테고리의 다른 글

[Python] __iter__ method of class at add operator with list...  (0) 2017.05.19

+ Recent posts