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

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


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

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

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

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


예를 들어, 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팀 실무자는 반대의 상황에 놓이게 될 것이다.


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

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

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


Since Linux 2.6.33, sendfile supports regular file as output file.
That is, sendfile can be used as way for fast file copy.
(Faster than normal read -> write operation because it is done inside kernel! )
Please refer follow example code ...

...


#include <stdio.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int
main(int argc, const char *argv[]) {
	int ifd, ofd, r;
	struct stat st;

	r = stat(argv[2], &st);
	r |= (ofd = open(argv[1], O_WRONLY | O_CREAT));
	r |= (ifd = open(argv[2], O_RDONLY));
	if (r < 0)
		return 1;
	if (-1 == sendfile(ofd, ifd, 0, st.st_size))
		return 1;
	fchmod(ofd, 0664);
	return 0;
}


...

Code...


#!/bin/bash

if [[ x$1 = x ]]; then
    f=${1:-/proc/${$}/fd/0}
else
    f=$1
fi

while read line
do
    echo $line
done < $f


[ Tested on Android 4.4_r1 with 3.4 goldfish kernel ]


android NDK의 경우 alloc하지 않은 메모리를 free하더라도 allocate된 영역이라면, 에러(segmentation fault)를 발생시키지 않는것 같다.

물론 그렇다고해서 정상적으로 free된다는 뜻은 아니다. 아래의 code와 비슷한  형태로 test code를 만들고, 실험해 보면, 메모리 leak이 발생하고 있음을 쉽게 알 수 있다.

test code는 아래와 같다.

#include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv) { char *p = malloc(4096 * 5); p += 2 * 4096; free(p); // <= error가 발생하지 않음. 그렇다고 해서 free되는 것도 아님. p+=10000000; free(p); // <= "[1] + Stopped (signal)" 발생... (이게 기대했던 건데...) return 0; }

쩝....

이건, Device의 libc에서 지원해 줘야 하는데, bionic의 dlmalloc compile option에서 'DEBUG' option을 켤 경우, 이 문제가 해결된다...

뭐.. 속도를 위해서 희생한 거니... 어쩔 수 없다지만... 그래도 아쉽긴... 아쉽다...

<< DEBUG switch 켜기 >>

diff --git a/libc/upstream-dlmalloc/malloc.c b/libc/upstream-dlmalloc/malloc.c
index 3ef9b61..9efc27d 100644
--- a/libc/upstream-dlmalloc/malloc.c
+++ b/libc/upstream-dlmalloc/malloc.c
@@ -520,7 +520,7 @@ MAX_RELEASE_CHECK_RATE   default: 4095 unless not HAVE_MMAP
   disable, set to MAX_SIZE_T. This may lead to a very slight speed
   improvement at the expense of carrying around more memory.
 */
-
+#define DEBUG 1 /* YHCHO test */
 /* Version identifier to allow people to support multiple versions */
 #ifndef DLMALLOC_VERSION
 #define DLMALLOC_VERSION 20806


지급이 높아질 수록 다른 사람에게 책임/권한을 부여해야할 일이 생기게 된다. (혼자서 모든 일을 할 수 없으므로, 누군가에게 일을 맡겨야 한다.)

이때, 조직의 공식적인 관계(결재/인사평가 에 직접적인 영향을 주지 못하는 관계 - ex. 직급에 차이가 있다 하더라도, 팀장/팀원의 관계가 아닌, 팀원/팀원의 관계)로 맺어지지 않은 사람들을 한 그룹으로 묶어야 하는 경우가 종종 생기게 된다.

예를 들어 아래와 같은 상황을 가정해 보자.

ex. 팀장(수석): A책임 B 선임 데리고 이 일좀 맡아서 해!


이때, A, B는 모두 팀장에게 평가를 받는 같은 위치의 팀원일 뿐이다. 비록 한명은 책임이고, 한명은 선임일 지라도...


아래와 같은 세 가지 경우를 생각해 보자.

경우 1. A에게만 위와 같은 이야기를 전하고, A에게 맡겨 둔다.

경우 2. A, B가 같이 있는 자리에서 두 사람에게 동시에 이 이야기를 전달한다.

경우 3. 팀 회의에서 이야기를 전달한다.


세가지 경우, 모두 특별한 문제가 생기지는 않겠으나, '1' 보다는 '2', '2' 보다는 '3'의 경우가 A에게 '힘'을 실어준다는 측면에서 더 나아 보인다.

그리고, 이 후 팀장이 B와 개인적인 대면을 통해서, A에 대한 칭찬(비록 약간 과장 되었다고 할지라도) - 'A는 충분히 B를 리드할 만 하고, 따를만한 가치가 있는 사람이다.' 라는 생각을 B에게 심어 주기 위해 - 과 함께 , A를 잘 따르라는 이야기를 전달함으로서 더욱 A에게 힘을 실어 줄 수 있다.

또한, 필요하다면, '팀장이 B에 대한 인사평가에 A의 의견을 적극 반영하겠다.'라는 이야기까지 진행함으로써 , A가 B와 함께 일함에 있어서 생길 수 있는 관계상의 문제에 마침표를 찍을 수도 있을 것이다.


어찌보면, 회사에서 '인사평가 line 혹은 report line으로 대표되는 공식적인 관계'를 만들어 두는 것 역시 위에서 언급한 '팀장' 이 A에게 힘을 실어주는 방식과 원칙적인 측면에서 다르지 않다고 볼 수 있다. 즉, 회사차원에서 힘을 실어주는 행위일 것이다.

다만, 여기서 언급하고자 하는 것은, 조직 전체라는 큰 그림에서만 이런 '힘을 실어주는 행위'가 필요한 것이 아니라, 작은 조직, 크게는 '서열'이라는 관계를 형성하는 모든 경우에, 위와 같은 '힘을 실어주는 행위'가 필요하다는 점이다.


단! 여기서 주의할 점이 하나 있다. 위의 예시의 경우에서, "A책임이 팀장의 편애"를 받고 있다고 B선임이 생각해 오고 있었다면, 위와 같은 "힘을 실어주기"는 오히려 '반발'을 불러 올 수도 있다!


selectpollpipe등에 대해서 block하면서 event(읽을 수 있게 되는 상태)를 기다리기 위해서 많이 쓴다.

man page를 보면...

       select()  and pselect() allow a program to monitor multiple file descriptors, waiting until
       one or more of the file descriptors become "ready" for some class of I/O  operation  (e.g.,
       input  possible).   A  file descriptor is considered ready if it is possible to perform the
       corresponding I/O operation (e.g., read(2)) without blocking.

그렇지만 자칫 오해하면, 일반 파일에 대해서 새로 추가된 내용이 있는지 검사하고 새로 추가된 내용을 읽어들이기 위해서 selectpoll을 사용할 수 있을 거라고 기대할 수도 있다.

그렇지만, select/poll은 man page에 언급한 바처럼, "IO가 block되지 않고 IO를 행할 수 있는 상태"를 기다린다.

file descriptorread() operation을 통해서 EOF에 도달하더라도, read() operation은 blocking없이 계속해서 수행가능하다는 점 - 비록 계속 0 byte를 읽겠지만... - 을 생각해보면, 위와 같은 생각은 적합하지 않다는 것을 알 수 있다.

주의하자!


아래는 간단한 test code이다. 1초마다 계속해서 read() 가 정상 수행됨을 알 수 있다.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <error.h>
#include <errno.h>

int
main(int argc, const char *argv[]) {
	char buf[4096];
	fd_set rfds;
	struct timeval tv;
	int fd, rb, retval;

	if (-1 == (fd = open("tstf", O_RDONLY)))
		perror("open tstf");

	/* Wait up to five seconds. */
	tv.tv_sec = 60;
	tv.tv_usec = 0;

	while (1) {
		/* Watch stdin (fd 0) to see when it has input. */
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);

		retval = select(fd + 1, &rfds, NULL, NULL, &tv);
		/* Don't rely on the value of tv now! */

		if (retval == -1)
			perror("select()");
		else if (retval) {
			printf("Data is available now.\n");
			memset(buf, 0, sizeof(buf));
			if (-1 == (rb = read(fd, buf, sizeof(buf) - 1)))
				fprintf(stderr, "%s", strerror(errno));
			printf("%s", buf);
			if (rb < (sizeof(buf) - 1))
				printf("\n---------------------------\nReaches to EOF\n");

			/* FD_ISSET(0, &rfds) will be true. */
		} else
			printf("No data within 1 minutes.\n");
		sleep(1);
	}
	exit(EXIT_SUCCESS);
}

DONE.

아래의 간단한 layout xml을 보자...


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@+id/button" <=== 여기

    tools:context=".MainActivity" >

    <Button

        android:id="@+id/button"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="say hello" />

</RelativeLayout>



자... paddingTop에는 당연히 dimension이 들어가야 한다. 그런데... 일부로 엉뚱하게도 '@+id/button'을 넣어봤다.

그런데.. compile error가 발생하지 않는다.!

resource compiler가 실제 id를 찾아서 id의 type을 읽어서 판단해 주지는 못하는 것으로 보인다.

대신 runtime에 아래와 같은 error를 발생시킨다.


11-09 02:47:49.750: E/AndroidRuntime(975): FATAL EXCEPTION: main

11-09 02:47:49.750: E/AndroidRuntime(975): Process: com.example.ttstest, PID: 975

11-09 02:47:49.750: E/AndroidRuntime(975): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ttstest/com.example.ttstest.MainActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class android.widget.RelativeLayout

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2176)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2226)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.ActivityThread.access$700(ActivityThread.java:135)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.os.Handler.dispatchMessage(Handler.java:102)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.os.Looper.loop(Looper.java:137)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.ActivityThread.main(ActivityThread.java:4998)

11-09 02:47:49.750: E/AndroidRuntime(975): at java.lang.reflect.Method.invokeNative(Native Method)

11-09 02:47:49.750: E/AndroidRuntime(975): at java.lang.reflect.Method.invoke(Method.java:515)

11-09 02:47:49.750: E/AndroidRuntime(975): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)

11-09 02:47:49.750: E/AndroidRuntime(975): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)

11-09 02:47:49.750: E/AndroidRuntime(975): at dalvik.system.NativeStart.main(Native Method)

11-09 02:47:49.750: E/AndroidRuntime(975): Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class android.widget.RelativeLayout

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.createView(LayoutInflater.java:620)

11-09 02:47:49.750: E/AndroidRuntime(975): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:669)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:694)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.inflate(LayoutInflater.java:469)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.inflate(LayoutInflater.java:397)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.inflate(LayoutInflater.java:353)

11-09 02:47:49.750: E/AndroidRuntime(975): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.Activity.setContentView(Activity.java:1928)

11-09 02:47:49.750: E/AndroidRuntime(975): at com.example.ttstest.MainActivity.onCreate(MainActivity.java:23)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.Activity.performCreate(Activity.java:5243)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)

11-09 02:47:49.750: E/AndroidRuntime(975): ... 11 more

11-09 02:47:49.750: E/AndroidRuntime(975): Caused by: java.lang.reflect.InvocationTargetException

11-09 02:47:49.750: E/AndroidRuntime(975): at java.lang.reflect.Constructor.constructNative(Native Method)

11-09 02:47:49.750: E/AndroidRuntime(975): at java.lang.reflect.Constructor.newInstance(Constructor.java:423)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.LayoutInflater.createView(LayoutInflater.java:594)

11-09 02:47:49.750: E/AndroidRuntime(975): ... 23 more

11-09 02:47:49.750: E/AndroidRuntime(975): Caused by: java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x12

11-09 02:47:49.750: E/AndroidRuntime(975): at android.content.res.TypedArray.getDimensionPixelSize(TypedArray.java:464)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.View.<init>(View.java:3560)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.View.<init>(View.java:3475)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.view.ViewGroup.<init>(ViewGroup.java:464)

11-09 02:47:49.750: E/AndroidRuntime(975): at android.widget.RelativeLayout.<init>(RelativeLayout.java:236)

11-09 02:47:49.750: E/AndroidRuntime(975): ... 26 more



쩝... layout을 작성할때는.. 항상 조심하자...

compiler가 이런걸 걸러주지 못하니... 조심스럽게 작성해야 할 수 밖에...

Creating libraries - Static library, shared library

NOTE : In case jni shared library, 'jni' code should in shared library source code. That is, you can put all other source codes in static library, but 'jni' should NOT in static library source

[ Android.mk ] for libraries for NDK.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS) LOCAL_MODULE := libX LOCAL_SRC_FILES := src0.c src1.c ... LOCAL_CFLAGS += LOCAL_C_INCLUDES += include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libXS LOCAL_SRC_FILES := jni.c LOCAL_CFLAGS += LOCAL_C_INCLUDES += LOCAL_STATIC_LIBRARIES := libX include $(BUILD_SHARED_LIBRARY)

Now you can find

shared library in <project root>/libs/armeabi/

static library in <project root>/obj/local/armeabi/



Creating executable with prebuilt static library (ex. static library built above - libX.a)


[ Android.mk ] for libraries for NDK.

LOCAL_PATH := $(call my-dir) ####################################################### # ####################################################### include $(CLEAR_VARS) LOCAL_MODULE := myexe LOCAL_SRC_FILES := main.c LOCAL_CFLAGS := LOCAL_LDFLAGS := LOCAL_C_INCLUDES += LOCAL_LDLIBS := -L <example/above/libX/project/root>/obj/local/armeabi/ -lX include $(BUILD_EXECUTABLE)

Now you can get 'myexe' executable.


* 서로 잘 모르는 관계에서 어떤 토의를 하거나, 요구사항 등을 받아들일 때, - 예를 들면, 해외 지사에서, 업무에 불편한 점이 없는지, 도와줄 일은 없는 지 등을 조사할 경우 - 는 반드시 아래의 사항들을 먼저 언급하고 시작해야, 서로간 잘못된 의사소통에 따른 비용을 최소화 할 수 있다.

- 이번 토의/회의 의 명확한 목적

ex: 제안을 받아 들여 달라, xxx를 해 달라 등등

- (제안/요구 를 듣는 입장의 경우) 나의 R&R, 할 수 있는 일과 한계 등.


* Software 업계에서 자주 나오는 이야기 중 "Software중에 '보안'을 이야기할 정도로 정말 가치있는 부분은 얼마 되지 않는다"라는 말이 있다. 수많은 좋은 Opensource software가 넘쳐나는데, 회사의 software중 보안이라는 이름으로 권한을 정밀하게 할 가치가 있는 부분은 얼마나 있을까? 너무 넓은 범위, 정밀한 permission체계는 실무자들에게 쓸데없는 Overhead 및 불편함을 만들 가능성이 굉장히 높다.


* 내가 그 사람의 일(작업)을 control할 수 있는 위치가 아니라면, 가능하면, feedback은 긍정적으로 하자.

ex)

Proposal : '이런 이런' 아이디어가 있고, 이렇게 하면 '이런 이런'게 좋아집니다. 어떤가요?

+ 내가 그 사람의 상관(관리자)라면 : 좋으면 -> OK, 나쁘면 -> NO. 만약 idea가 받아 들이기 힘들다면 NO.. etc.

왜냐하면, 그 사람이 하는 일 및 시간을 관리해야 하는 위치이기 때문에, 필요없는 일을 하는 것들 두고 보는 것은 업무에 도움이 되지 않는다.

+ 만약 내가 3자의 입장이라면 : '이런 이런' 점들이 걱정되지만(뭔가 feedback을 원하는 경우이므로, 내가 관심이 있다는 것을 알려 주기위해 feedback은 해 주어야 한다.), 그렇게만 되면 정말 좋겠군요. 꼭 성공하세요.(마지막 feedback은 항상 긍정적이여야 한다. 나는 불가능하다고 생각하지만, 그 사람은 그것을 정말로 해 낼 수 있을지도 모르기 때문이다.)

나랑 관계없는 사람/일 에 굳이 부정적인 feedback을 주어서, 미움을 살 필요는 없다.


* Project에 대한 발표(Presentation)시, Risk에 대한 언급을 포함하고 있지 않다면 그 발표는 문제가 있는 것이다!

무엇이 문제인지도 모르는(고려해 보지 않은) Project description이 제대로 된 것일리 만무하다.


* Project Schedule이 "꼭 해야만 하는 일"로 꽉 차 있다면, Risk에 대해 전혀 고려되어 있지 않다는 것이다!

Project Schedule에 "꼭 해야하지는 않으나, Risk 완화를 위해 필요한 일"을 위한 시간이 포함되어 있어야 한다.


* Project 완료 시간이 너무 촉박하다면, 그 Project는 너무 늦게 시작된 것이다.(해당 사업계획을 잘못 세웠다는 말이다.)

기획/계획 쪽에서도 책임을 져야한다.







Some notable points when using mmap 

- mapping with MAP_PRIVATE doesn't carry updates through to the underlying file.

- mmap writing to file is deferred.

=> use msync to write back to file at certain time.

- See also, mprotect, madvise ...


mmap and memory(smaps).

protection argument and flag of mmap matches vma flags (ex. MAP_PRIVATE + PROT_READ | PROT_EXEC <=> r-xp )


* mmap to generic file
Writing to mapped memory doesn't increase process's memory usage(RSS) - doesn't request process's memory page.(I think just memory for disk cache is affected by this operation.)


* mmap to anonymous - MAP_PRIVATE
Demanded pages are treated as PrivateDirty (just like malloc)


map = mmap(NULL, mapsz, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);


there is only one VMA(size = mapsz) - Virtual Memory Area - for this map. And it's flag will be ---p.


mprotect(map, mapsz / 3, PROT_WRITE);


Now, two VMAs are used for this map.
One(vma0) is VMA(-w-p) whose size is mapsz / 3. The other(vma1) is VMA(---p) whose size is mapsz / 3 * 2.


sz = mapsz / 3; while (sz--) map[sz] = 0xff;


Now, vma0 has PrivateDirty (size = mapsz / 3) because pages are demanded and written.

* mmap to anonymous - MAP_SHARED   
Same with above. But, shared flag is used instead of private flag.
And in case of shared memory, PSS is very valuable information along with RSS.

(to be continued...)

+ Recent posts