구글의 Python Tutorial

[번역] 구글의 파이썬 튜토리얼 요약.
원문은 Google’s Python Class(https://developers.google.com/edu/python/)

* Python 환경 설정

나올 때 윈도우에서는 Ctrl-Z, 다른 OS에서는 Ctrl-D

* Introduction

if __name__ == ‘__main__’:
    main()

sys.argv[0]는 프로그램 이름, sys.argv[1]은 첫번째 인자, sys.argv[2]는 두번째 인자…

TAB 문자 대신 Space들을 입력.

help(len) : len 함수에 대한 문서를 출력
dir(sys): sys 모듈에 대한 전반적인 문서
help(sys.exit): sys 내의 exit() 함수에 대한 문서

* Strings

파이썬 스트링은 “immutable”하다. 즉, 생성 후에 값을 변경할 수 없다. 따라서 다른 값이 되면 새로운 스트링이 생성된다.

“”” 로 여러줄 string 가능

[ ]로 문자 접근 가능
Slice로 substring 얻기
len(string) 은 string의 길이. sequence 타입에는 다 사용 가능
‘+’ 로 concatenate.

Value를 string 으로 변경하고 싶을 때는 str() 함수를 사용

pi = 3.14
text = ‘The value of pi is ‘ + str(pi)

정수로 나눗셈을 할 때는 // 를 사용. 6 // 5 == 1

print 뒤에 줄바꿈을 하고 싶지 않으면 마지막에 , 를 붙인다.
r 을 앞에 붙이면 ‘raw’ string. \ 를 특별히 취급하지 않는다. r’x\nx’ 는 ‘x\nx’ 가 됨. u 를 앞에 붙이면 unicode.

s.lower(), s.upper(): 소문자, 대문자로
s.strip(): 앞 뒤의 whitespace 제거
s.isalpha() / s.isdigit() / s.isspace(): 알파벳인지, 숫자인지, space인지
s.startswith(‘other’), s.endswith(‘other’): s 스트링이 다른 특정 스트링으로 시작하거나 끝나는지.
s.find(‘other’): s 스트링 안의 다른 스트링을 찾는다. 찾으면 인덱스 리턴, 못찾으면 -1
s.replace(‘old’, ‘new’): 모든 ‘old’를 ‘new’로 변경한 string 리턴
s.split(‘delim’): 주어진 delimiter로 자른 substring 리스트를 리턴,
s.join(list): split()의 반대, s를 delimiter로 리스트를 합친다.

길이가 1인 string 에 ==, <= 등의 작업을 할 수 있다. char 타입이 따로 없다.

H  e  l  l  o
0  1  2  3  4
-5 -4 -3 -2 -1

s[1:4]는 ‘ell’, s[1:]는 ‘ello’, s[:]는 ‘Hello’의 복사본, s[1:100]은 ‘ello’ – 더 큰 index를 사용하면 string의 length나 마찬가지가 된다.
s[-1]은 ‘o’, s[-4]은 ‘e’, s[:-3]은 ‘He’, s[-3:]은 ‘llo’
s[:n] + s[n:] == s 는 항상 참. n이 음수거나, index영역을 벗어났을 때도 성립.

% 연산자를 사용해 printf 같은 format string. %d는 int, %s는 string, %f/%g는 float, 오른쪽에 튜플.

text = “%d little pigs come out or I’ll %s and %s and %s” % (3, ‘huff’, ‘puff’, ‘blow down’)

너무 길면 전체 expression을 괄호로 싸면 된다.

text = (“%d little pigs come out or I’ll %s and %s and %s” %
    (3, ‘huff’, ‘puff’, ‘blow down’))

unistring.encode()와 unicode로 encoding 변환.

s = unistring.encode(‘utf-8’)
t = unicode(s, ‘utf-8’)
t == unistring

if / elif/ else. “zero” 값들(None, 0, “”, ”, [], {}, False)은 false, True/False로 boolean 값, and, or, not 사용. ()로 expression 을 감싸지 않는다.

* Lists

= 을 사용하면 그냥 reference.
‘+’ 를 사용해 list를 합칠 수 있다.

for와 in 으로 iteration

squares = [1, 4, 9, 16]
sum = 0
for num in squares:
    sum += num
print sum ## 30

in 은 독립적으로 어떤 원소가 list(또는 다른 collection)에 있는지 테스트 할 수 있다.

list = [‘larry’, ‘curly’, ‘moe’]
if ‘curly’ in list:
    print ‘yay’

range(n)은 0, 1, 2, …, n-1 까지의 숫자를 리턴. range(a, b) 는 a, a+1, a+2, …, b-1 까지를 리턴.

for i in range(100):
    print i

xrange()는 전체 리스트를 만드는 과정을 없애 성능 상 좋다.

while

i = 0
while i < len(a):
    print a[i]
    i = i + 3

list.append(elem): 리스트를 수정하여 가장 뒤에 elem 추가. 리턴하지 않는다.
list.insert(index, elem): index에 elem을 추가. 리턴하지 않는다.
list.extend(list2): list2의 원소들을 list에 추가. 리턴하지 않는다.
list.index(elem): elem이 있으면 index 리턴, 없으면 ValueError를 발생. ValueError 없이 확인하려면 in 을 사용.
list.remove(elem): 첫번째 elem을 제거, 없으면 ValueError. 리턴하지 않는다.
list.sort(): list를 sort. 리턴하지 않는다. sorted()를 더 자주 사용.
list.reverse(): list를 역순으로 변경. 리턴하지 않는다.
list.pop(index): index의 원소를 제거하고 리턴. index를 생략하면 가장 끝의 원소를 리턴(append()와 반대)

* Sorting

sorted()를 사용. reverse=True를 전달하면 역순. Case sensitive하다.

strs = [‘aa’, ‘BB’, ‘zz’, ‘CC’]
print sorted(strs) ## [‘BB’, ‘CC’, ‘aa’, ‘zz’] 
print sorted(strs, reverse=True) ## [‘zz’, ‘aa’, ‘CC’, ‘BB’]

key로 함수를 전달하면 해당 함수를 key로 정렬. key=len, key=str.lower 하면 대소문자 동일하게 취급하여 정렬.

print sorted(strs, key=str.lower) ## [‘aa’, ‘BB’, ‘CC’, ‘zz’]

key로 custom 함수 전달 가능

def MyFn(s):
    return s[-1]
print sorted(strs, key=MyFn)

cmp=cmpFn 선택 인자를 전달할 수도 있음. 내장 함수는 cmp(a, b)로 -/0/+ 로 순서를 리턴

Tuple은 struct와 비슷한 역할. 변경 불가능, 크기가 변하지 않음. () 를 통해 만듦. 크기가 1인 튜플은 ( 1, ) 처럼 , 을 넣어 만듦.

변수 할당에 사용 가능. 반환값이 여러 값을 가진 경우도 사용 가능
(x, y, z) = (42, 13, “Hike”)
(err_string, err_code) = foo()

[ _expr_ for var in list ] 형태로 원하는 형태의 리스트 생성 가능.

fruits = [‘apple’, ‘cherry’, ‘banana’, ‘lemon’]
afruits = [ s.upper() for s in fruits if ‘a’ in s ] ## [‘APPLE’, ‘BANANA’]

* Dictionaries and Files

dict = {}
dict[‘a’] = ‘alpha’
dict[‘g’] = ‘gamma’
dict[‘o’] = ‘omega’

print dict[‘a’] ## ‘alpha’
dict[‘a’] = 6
‘a’ in dict ## True
## print dict[‘z’] ## Throws KeyError
if ‘z’ in dict: print dict[‘z’] ## KeyError를 피한다.
print dict.get(‘z’) ## None

dict.get(key, not-found) 형태로 키가 없을 경우 not-found 로 설정한 값을 리턴하도록 할 수도 있다.

dict.keys(): key 리스트
dict.values(): value 리스트
dict.items(): (key, value) 튜플의 리스트

for k, v in dict.items(): print k, ‘>’, v

iterkeys(), itervalues(), iteritems()는 전체 리스트를 만들지 않아 성능 상 좋다.

hash = {}
hash[‘word’] = ‘garfield’
hash[‘count’] = 42
s = ‘I want %(count)d copies of %(word)s’ % hash # ‘I want 42 copies of garfield’

del 로 변수, list 원소, dict key/value를 지울 수 있다.

Files open(), close(). open 시 ‘rU’를 사용하면 줄바꿈을 ‘\n’으로 변형하여 준다.

f = open(‘foo.txt’,’rU’)
for line in f: ## 파일을 한 줄씩 방문
    print line, ## line 끝에 이미 줄바꿈이 포함되어 있으므로 print가 줄바꿈하지 않도록 한다.
f.close()

f.readlines()는 전체를 메모리에 올리고 줄들의 list를 리턴, read()는 전체 파일을 하나의 string으로.

파일에 쓰려면, f.write(string). print를 사용하려면, print >> f, string. python 3에서는 print(string, file=f)

codes는 unicode를 읽을 때 사용 가능

import codecs
f = codecs.open(‘foo.txt’, ‘rU’, ‘utf-8’)
for line in f: # line은 unicode string이 됨.

* Regular expression

import re
str = ‘an example word:cat!!’
match = re.search(r’word:\w\w\w’, str)
if match:
    print ‘검색 성공’, match.group() ## 발견 word:cat
else
    print ‘검색 실패’

패턴 스트링은 항상 r로 시작.

a, X, 9: 있는 그대로의 문자를 매치
.: 아무 문자 하나를 매치. \n 은 제외
\w: 하나의 word에 쓰이는 문자 하나를 매치(단어가 아님). a-z, A-Z, 0-9, _ [a-zA-Z0-9_]를 매치.
\W: non-word에 쓰이는 문자 하나를 매치
\b: word와 non-word의 경계
\s: 하나의 whitespace 문자[ \n\r\t\f]를 매치
\S: whitespace 이외의 문자를 매치
\d: 숫자 [0-9]
^: 시작
$: 끝
\를 붙여 위의 것들을 그저 문자로 사용 가능

+: 왼쪽 패턴 1개 이상.
*: 왼쪽 패턴 0개 이상.
?: 왼쪽 패턴 0개 혹은 1개
+와 *는 가장 왼쪽의 것을 찾고, greedy 하다. 

r'[\w.-]+@[\w.-]+’ 로 @ 주위에 ‘.’와 ‘-‘도 매치하도록 할 수 있다. -가 구간을 매치하지 않도록 하려면 가장 마지막에 넣는다.
[] 안의 내용을 ^로 시작하면 집합을 뒤집는다. [^ab]는 ‘a’와 ‘b’를 제외한 모든 문자를 뜻한다.

패턴 안에 ( )를 넣으면 그룹으로 구분할 수 있게 해준다.

str = ‘purple alice-b@google.com monkey dishwasher’
match = re.search(r'([\w.-]+)@([\w.-]+)’, str)
if match
    print match.group() ## ‘alice-b@google.com’
    print match.group(1) ## ‘alice-b’
    print match.group(2) ## ‘google.com’

findall(): 모든 패턴에 해당하는 string 리스트를 리턴

f = open(‘text.txt’, ‘r’)
strings = re.findall(r’some pattern’, f.read())

findall 에 ( )를 넣으면 그룹에 해당하는 튜플 리스트를 만든다.

str = ‘purple alice@google.com, blah monkey bob@abc.com blah dishwasher’
tuples = re.findall(r'(\w\.-]+)@([\w\.-]+)’, str)
print tuples ## [(‘alice’, ‘google.com’), (‘bob’, ‘abc.com’)]
for tuple in tuples:
    print tuple[0] ## username
    print tuple[1] ## host

re.search(pat, str, re.IGNORECASE) 처럼 추가 옵션 가능
IGNORECASE: 대소문자 구별하지 않음
DOTALL: 마침표 . 이 newline을 매치하도록 한다. 보통은 newline을 제외한 모든것들을 매치.
MULTILINE: 여러줄로 이루어진 string에서 ^와 $가 줄의 시작과 끝을 매치하도록 한다. 보통은 ^ $는 전체 스트링의 시작과 끝을 매치한다.

정규 표현식의 확장으로 .*? 나 .+?처럼 ?를 끝에 더해서 greedy 하지 않게 변경할 수 있다.

str = ‘<b>foo</b> and <i>so on</i>’
match = re.search(r'(<.*>)’, str)
if match:
    print match.group() ##'<b>foo</b> and <i>so on</i>’
match = re.search(r'(<.*?>)’, str)
if match:
    print match.group() ## ‘<b>’

re.sub(pat, replacement, str) 은 str에서 pat과 매치되는 모든 스트링들을 찾아 replacement로 치환한다. replacement 스트링은 \1, \2 를 이용하여 group(1), group(2)를 표현할 수 있다.

str = ‘purple alice@google.com, blah monkey bob@abc.com blah dishwasher’
print re.sub(r'([\w\.-]+)@([\w\.-]+)’, r’\1@yo-yo-dyne.com’, str)
# purple alice@yo-yo-dyne.com, blah monkey bob@yo-yo-dyne.com blah dishwasher

* Utilities

os 모듈
filenames = os.listdir(dir): dir에 있는 .과 ..을 제외한 파일이름들의 리스트, 절대경로가 아님.
os.path.join(dir, filename): filename과 dir을 합쳐서 path를 만든다.
os.path.abspath(path): path를 받아서 절대 경로를 리턴
os.path.dirname(path), os.path.basename(path): dir/foo/bar.html을 받아서 dirname ‘dir/foo’와 basename’bar.html’을 리턴
os.path.exists(path): path 가 존재하면 True를 리턴
os.mkdir(dir_path): dir 하나를 만든다.
os.makedirs(dir_path): dir_path를 만들기 위한 모든 디렉토리들을 만든다.
shutil.copy(source-path, dest-path): 파일을 복사한다. 복사될 디렉토리가 존재해야 한다.

commands 모듈: 외부 명령을 실행하고 결과물을 얻어옴.
(status, output) = commands.getstatusoutput(cmd): cmd를 실행하고 exit할 때까지 기다려서,
status int값과 output text를 tuple로 리턴한다. stdout과 stderr이 하나의 출력물로 합쳐져서 나타난다.
output = commands.getoutput(cmd): 위와 동일, status값을 받지 않는다는 것만 다름.
commands.getstatus() 라는 함수는 사용하지 말아라.
sub-process에 대한 더 많은 제어권을 원하면 “popen2” 모듈을 보라.
os.system(cmd): cmd의 결과물을 여러분 코드의 output으로 출력하고, error 코드를 리턴.

try/except. ‘except IOError, e:’ 의 형태로 exception 객체에 대한 포인터를 얻을 수 있다.

try:
  f = open(filename, ‘rU’)
  text = f.read()
  f.close()
except IOError:
  sys.stderr.write(‘problem reading:’ + filename)

urllib 모듈: url을 마치 file처럼 읽을 수 있게 한다. urlparse 모듈은 url을 분해하거나 합치는 기능을 제공
ufile = urllib.urlopen(url): url에 대한 file 같은 객체를 리턴
text = ufile.read(): 파일처럼 읽음. readlines()도 사용 가능
info = ufile.info(): 요청에 대한 meta 정보를 리턴. info.gettype() 으로 ‘text/html’ 같은 mime 타입을 얻어 옴.
baseurl = ufile.geturl(): 요청에 대한 “base” url을 얻어옴. redirect로 인해 open할 때 사용한 url과 다를 수 있다.
urllib.urlretrieve(url, filename): url의 데이터를 다운받아 filename의 file로 저장한다.
urlparse.urljoin(baseurl, url): full url을 만든다.

def wget2(url):
  try:
    ufile.urllib.urlopen(url)
    if ufile.info().gettype() == ‘text/html’:
      print ufile.read()
  except IOError:
    prit ‘problem reading url:’, url

[Linux:Kernel] Documentation/io-mapping.txt

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under GPL license).
Documentation/io-mapping.txt
번역: 양정석 <dasomoli@gmailREMOVETHIS.com>
linux/io-mapping.h 안의 io_mapping 함수들은 CPU에 I/O 디바이스들의 작은 영역을
효율적으로 맵핑하는 추상화를 제공합니다. 애초의 용도는 ioremap_wc가 커널 주소
영역을 너무 많이 소비할 때 처럼 CPU에 전체 영역을 정적으로 맵핑할 수 없을 때,
32비트 프로세서들에서 큰 그래픽 영역을 제공하기 위함입니다.
맵핑 객체는 드라이버 초기화 중에 다음을 사용하여 생성합니다
        struct io_mapping *io_mapping_create_wc(unsigned long base,
                                                unsigned long size)
                ‘base’는 맵핑 가능하게 만들어 질 영역의 버스 주소인 반면,
                ‘size’는 얼마나 크게 영역을 맵핑할 것인지를 나타냅니다.
                둘다 바이트 수 입니다.
                이 _wc 변형은 io_mapping_map_atomic_wc나 io_mapping_map_wc로만
                사용할 수 있는 맵핑을 제공합니다.
이 맵핑 객체로, 개별 페이지들이 자동적으로, 혹은 아니게 필요한 스케줄링 환경에
따라 맵핑될 수 있습니다. 물론, 어토믹 맵핑은 더 효율적입니다:
        void *io_mapping_map_atomic_wc(struct io_mapping *mapping,
                                       unsigned long offset)
                ‘offset’은 정의된 맵핑 영역 안에서의 오프셋입니다. 생성 함수
                에서 지정된 영역을 넘어서서 주소를 접근하는 것은 정의되지
                않은 결과를 불러옵니다. 페이지 정렬되지 않은 오프셋을
                사용하는 것도 정의되지 않은 결과를 불러옵니다. 반환 값은
                CPU 주소 공간 안의 한 페이지를 가리킵니다.
                이 _wc 변형은 페이지로의 write-combining 맵핑을 반환하고,
                io_mapping_create_wc에 의해 생성된 맵핑에만 사용가능합니다.
                태스크가 이 맵핑된 페이지를 잡고 있는 동안 슬립하지 않음을
                알아두세요.
        void io_mapping_unmap_atomic(void *vaddr)
                ‘vaddr’은 반드시 마지막 io_mapping_map_atomic_wc 호출에
                의해 반환된 값이어야 합니다. 이것은 지정된 페이지를 맵핑
                해제하고 그 태스크가 다시 한번 잠들 수 있게 합니다.
여러분이 그 락을 잡은 동안 슬립해야할 필요가 있다면, 극히 더 느리긴 하지만,
어토믹이 아닌 변형을 사용할 수 있습니다.
        void *io_mapping_map_wc(struct io_mapping *mapping,
                                unsigned long offset)
                이것은 태스크가 맵핑된 페이지를 잡고 있는 동안 슬립할 수 있다는
                것을 제외하면 io_mapping_map_atomic_wc와 같이 동작합니다.
        void io_mapping_unmap(void *vaddr)
                이것은 io_mapping_map_wc로 매핑된 페이지들이 사용되는 것을
                제외하면 io_mapping_unmap_atomic과 같이 동작합니다.
드라이버에 가까운 시간에, io_mapping 객체는 반드시 해제되어야만 합니다:
        void io_mapping_free(struct io_mapping *mapping)
현재 구현:
이들 함수의 초기 구현은 이미 구현된 맵핑 메카니즘을 사용해서 오직 추상 계층만
제공하고 새로운 기능은 없습니다.
64비트 프로세서에서 io_mapping_create_wc는 자원으로의 영구적으로 커널이 볼 수
있는 맵핑을 생성하는 전체 영역을 위해서 ioremap_wc를 호출합니다. 그 map_atomic과
map 함수들은 ioremap_wc에 의해 반환되는 가상 주소의 기준점으로부터의 요청된
오프셋을 더합니다.
HIGHMEM이 정의된 32비트 프로세서에서는 io_mappinc_map_atomic_wc가
kmap_atomic_pfn을 지정된 페이지를 어토믹하게 맵핑하는데 사용됩니다;
kmap_atimic_pfn은 디바이스 페이지와 사용될 것이라고 정말 여겨지지 않았습니다만,
이 용도를 위한 효율적인 맵핑을 제공합니다.
HIGHMEM 정의가 없는 32비트 프로세서에서는 io_mapping_map_atomic_wc와
io_mapping_map_wc 모두 새로운 맵핑을 모든 프로세서에 알리기 위해서 IPI를 수행하는
극악하게 비효율적인 함수인 ioremap_wc를 사용합니다. 이것은 극적인 성능 저하를
가져옵니다.

[Linux:Kernel] Documentation/printk-formats.txt

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under GPL license).

변수가 아래 타입이라면,           printk형식 지시자를 사용하세요:
———————————————————
                int                     %d 나 %x
                unsigned int            %u 나 %x
                long                    %ld 나 %lx
                unsigned long           %lu 나 %lx
                long long               %lld 나 %llx
                unsigned long long      %llu 나 %llx
                size_t                  %zu 나 %zx
                ssize_t                 %zd 나 %zx

가공되지 않은 포인터 값은 %p로 출력되는 것이 ‘좋습니다’. 커널은 포인터
형식을 위해 다음의 확장된 형식 지시자를 지원합니다:

심볼/함수 포인터:

        %pF     versatile_init+0x0/0x110
        %pf     versatile_init
        %pS     versatile_init+0x0/0x110
        %pSR    versatile_init+0x9/0x110
                (__builtin_extract_return_addr() 변환으로)
        %ps     versatile_init
        %pB     prev_fn_of_versatile_init+0x88/0x88

        심볼과 함수 포인터를 출력하기 위해서, (‘S’)로 오프셋과 함께, 혹은 (‘s’)로
        오프셋 없이, ‘S’와 ‘s’ 지시자들로 심볼 이름을 나타냅니다. KALLSYMS 없는
        커널 상에서 사용되면, 심볼 주소가 대신 출력됩니다.

        ‘B’ 지시자는 오프셋과 함께 심볼 이름을 나타내고, 스택 트레이스를 출력할
        때 사용되어야 합니다. 이 지시자는 Tail-Call이 사용되고, noreturn GCC 속성으로
        표시되었을 때 일어날 컴파일러 최적화의 효과를 고려하게 합니다.

        ia64, ppc64, 그리고 parisc64 아키텍처에서 함수 포인터들은 실제로는
        가장 먼저 풀어야 할 함수 기술자들입니다. ‘F’와 ‘f’ 지시자는 이 해결을
        수행하여 ‘S’와 ‘s’ 지시자와 같은 기능을 제공합니다.

커널 포인터:

        %pK     0x01234567 나 0x0123456789abcdef

        권한이 없는 사용자에게 가려져야 할 커널 포인터를 출력하기 위해서 사용.
        %pK의 동작은 kptr_restrict sysctl에 의존적입니다.
        – 더 자세한 사항은 Documentation/sysctl/kernel.txt를 보세요.

구조체 자원:

        %pr     [mem 0x60000000-0x6fffffff flags 0x2200] or
                [mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
        %pR     [mem 0x60000000-0x6fffffff pref] or
                [mem 0x0000000060000000-0x000000006fffffff pref]

        구조체 자원을 출력하기 위해 사용. ‘R’과 ‘r’ 지시자는 디코딩된 플래그
        멤버들이 있게(‘R’) 혹은 없게(‘r’) 자원을 출력합니다.

phys_addr_t 타입의 물리 주소:

        %pa[p]  0x01234567 나 0x0123456789abcdef

        CPU 데이터 경로의 너비와 상관없이, 빌드 옵션에 의해서 다양하게 될 수 있는
        phys_addr_t 타입(그리고 resource_size_t 같은 그 변형)의 출력을 위해서 사용.
        참조로 넘김.
        

dma_addr_t 타입의 DMA 주소:

        %pad    0x01234567 나 0x0123456789abcdef

        CPU 데이터 경로의 너비와 상관없이, 빌드 옵션에 의해서 다양하게 될 수 있는
        dma_addr_t 타입의 출력을 위해서 사용. 참조로 넘김.

16진수 문자열의 비가공 버퍼:
        %*ph    00 01 02  …  3f
        %*phC   00:01:02: … :3f
        %*phD   00-01-02- … -3f
        %*phN   000102 … 3f

        명확한 구분자로 된 16진수 문자열로 작은 버퍼(64 바이트 길이까지의)를
        출력할 때 사용. 더 큰 버퍼는 print_hex_dump()의 사용을 고려하세요.

MAC/FDDI 주소:

        %pM     00:01:02:03:04:05
        %pMR    05:04:03:02:01:00
        %pMF    00-01-02-03-04-05
        %pm     000102030405
        %pmR    050403020100

        16진수 표기로 된 6바이트 MAC/FDDI 주소를 출력할 때 사용. ‘M’과
        ‘m’ 지시자는 바이트 구분자가 있게(‘M’) 혹은 없게(‘m’) 주소를 출력합니다.
        기본 바이트 구분자는 콜론(‘:’)입니다.

        FDDI 주소들이 쓰이는 곳에서 ‘F’ 지시자는 기본 구분자 대신에 대시(‘-‘)
        구분자를 사용하기 위해서 ‘M’ 지시자 이후에 사용될 수 있습니다.

        블루투스 주소를 위해서 리틀 엔디언으로 된 블루투스 주소의 보이는 형태의
        거꾸로 된 바이트 순서 맞춤을 사용하기 위해서 ‘R’ 지시자가 쓰이면 좋습니다.

IPv4 주소:

        %pI4    1.2.3.4
        %pi4    001.002.003.004
        %p[Ii]4[hnbl]

        IPv4의 점으로 구분된 10진수 주소를 출력할 때 사용. ‘I4’와 ‘i4’ 지시자는
        앞 쪽 0들이 있게(‘i4’) 혹은 없게(‘I4’) 주소를 출력합니다.

        덧붙는 ‘h’, ‘n’, ‘b’, 그리고 ‘l’ 지사자들은 각각 호스트, 네트워크,
        빅 또는    리틀 엔디언 주소를 나타내는데 사용됩니다. 아무 지시자가 없다면,
        기본 네트워크/빅 엔디언 오더가 사용됩니다.

IPv6 주소:

        %pI6    0001:0002:0003:0004:0005:0006:0007:0008
        %pi6    00010002000300040005000600070008
        %pI6c   1:2:3:4:5:6:7:8

        IPv6 네트워크-오더 16비트 16진수 주소를 출력할 때 사용. ‘I6’와 ‘i6’
        지시자는 콜론 구분자가 있게(‘I6’) 혹은 없게(‘i6’) 주소를 출력합니다.
        앞 쪽의 0들은 항상 사용됩니다.
        
        덧붙는 ‘c’ 지시자는 ‘I’ 지시자와 함께 http://tools.ietf.org/html/rfc5952에
        쓰여 있는 압축된 IPv6 주소를 출력하는데 사용할 수 있습니다.

IPv4/IPv6 주소 (일반적인, 포트와 함께, flowinfo, 범위):

        %pIS    1.2.3.4         나 0001:0002:0003:0004:0005:0006:0007:0008
        %piS    001.002.003.004 나 00010002000300040005000600070008
        %pISc   1.2.3.4         나 1:2:3:4:5:6:7:8
        %pISpc  1.2.3.4:12345   나 [1:2:3:4:5:6:7:8]:12345
        %p[Ii]S[pfschnbl]

        그 타입이 AF_INET인지 AF_INET6인지 구분할 필요 없이 IP 주소를 줄력할 때
        사용. ‘IS’ 또는 ‘iS’를 통해 지정된 유효한 ‘struct socketaddr’로의
        포인터는 이 형식 지시자에게 넘겨질 수 있습니다.

        덧붙는 ‘p’, ‘f’, 그리고 ‘s’ 지시자는 포트(IPv4, IPv6), flowinfo(IPv6),
        범위(IPv6)를 지정하는데 사용됩니다. 포트는 “:” 접두어를 갖고, flowinfo는
        ‘/’, 그리고 스코프는 ‘%’를 갖고, 각각 실제 값이 뒤 따릅니다.

        IPv6 주소의 경우에 http://tools.ietf.org/html/rfc5952에서 기술된
        압축된 IPv6 주소는 지시자 ‘c’를 사용하면 사용됩니다. IPv6 주소는
        추가적인 지시자        ‘p’, ‘f’, ‘s’의 경우에
        https://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07 에
        제안된 것처럼 ‘[‘, ‘]’로 둘러싸입니다.

        IPv4 주소의 경우, 덧붙는 ‘h’, ‘n’, ‘b’, 그리고 ‘l’ 지시자가 잘 사용될 수
        있고, IPv6 주소의 경우에는 무시됩니다.

        더 많은 예제:

        %pISfc          1.2.3.4         나 [1:2:3:4:5:6:7:8]/123456789
        %pISsc          1.2.3.4         나 [1:2:3:4:5:6:7:8]%1234567890
        %pISpfc         1.2.3.4:12345   나 [1:2:3:4:5:6:7:8]:12345/123456789

UUID/GUID 주소:

        %pUb    00010203-0405-0607-0809-0a0b0c0d0e0f
        %pUB    00010203-0405-0607-0809-0A0B0C0D0E0F
        %pUl    03020100-0504-0706-0809-0a0b0c0e0e0f
        %pUL    03020100-0504-0706-0809-0A0B0C0E0E0F

        16바이트 UUID/GUID 주소를 출력하기 위해 사용. 덧붙는 ‘l’, ‘L’, ‘b’,
        그리고, ‘B’ 지시자는 리틀 엔디언 오더를 소문자(‘l’) 또는 대문자(‘L’)
        16진수 문자로 – 그리고 빅 엔디언 오더를 소문자(‘b’) 또는 대문자(‘B’)
        16진수 문자로 표시하는데 사용됩니다.

        아무 추가 지시자도 붙지 않으면 기본으로 리틀 엔디언 오더에 소문자로
        출력될 것입니다.

dentry 이름:
        %pd{,2,3,4}
        %pD{,2,3,4}

        dentry 이름을 출력하는데 사용; 만약 우리가 d_move()로 경쟁 상태를 만들면,
        그 이름은 오래된 것과 새 것이 섞일 것입니다. 웁스를 일으키지 않습니다.
        %pd dentry는 우리가 사용하곤 했던 %s dentry->d_name.name와 같지만 더
        안전합니다. %pd<n>은 마지막 n 컴포넌트를 출력합니다. %pD는 struct file에
        같은 동작을 합니다.

struct va_format:

        %pV

        struct va_fotmat 구조체를 출력하는데 사용. 이들은 다음과 같은 va_list와
        형식 문자열을 포함합니다:

        struct va_format {
                const char *fmt;
                va_list *va;
        };

        형식 문자열이나 va_list 인자들의 정확성을 확인하기 위한 어떤 메카니즘 없이
        이 기능을 사용하지 마세요.

u64는 %llu/&llx로 ‘출력해야’ 합니다:

        printk(“%llu”, u64_var);

s64는 %lld/%llx로 ‘출력해야’ 합니다:

        printk(“%lld”, s64_var);

Example:
<type>이 그 크기의 설정 옵션(예를 들면, sector_t, blkcnt_t)이나 그 크기의 아키텍처
(예를 들면, tcflag_t)에 의존적이라면, 가능한 가장 큰 타입의 형식 지시자를 쓰고
명시적으로 형을 변환하세요.
예제:

        printk(“test: sector number/total blocks: %llu/%llu\n”,
                (unsigned long long)sector, (unsigned long long)blockcount);

다시 알림: sizeof() 결과는 size_t 타입입니다.

여러분의 협력과 주의에 감사합니다.
By Randy Dunlap <rdunlap@infradead.org> and
Andrew Murray <amurray@mpc-data.co.uk>
그리고 우리말 번역에 양정석 <dasomoli@gmail.com>

[Linux:Kernel] AArch64 리눅스의 메모리 배치

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).

Documentation/arm64/memory.txt

     AArch64 리눅스의 메모리 배치
     ============================

Author: Catalin Marinas <catalin.marinas@arm.com>
번역  : 양정석 <dasomoli@gmailREMOVETHIS.com>
Date  : 20 February 2012

이 문서는 AArch64 리눅스 커널이 사용하는 가상 메모리 배치를 설명합니다.
이 아키텍처는 4KB 페이지 크기의 4단계 변환 테이블과 64KB 페이지 크기의
3단계 변환 테이블을 허용합니다.

AArch64 리눅스는 유저와 커널 양 쪽 모두 39비트 (512GB) 가상 주소를 허용하는
4KB 페이지 설정의 3단계 변환 테이블을 사용합니다. 64KB 페이지는 오직
2단계 변환 테이블이 사용되지만 메모리 배치는 같습니다.

유저 주소는 63:39 비트가 0으로 셋팅되는 반면, 커널 주소는 같은 곳의 비트에
1로 셋팅됩니다. TTBRx 선택은 가상 주소의 비트 63에 의해 결정됩니다.
swapper_pg_dir은 오직 커널 (전역) 맵핑만 포합하는 반면,
유저 pgd는 오직 유저 (비전역) 맵핑만 포함합니다. swapper_pgd_dir 주소는
TTBR1으로 쓰여지고, TTBR0로 절대 쓰여지지 않습니다.


4KB 페이지의 AArch64 리눅스 메모리 배치:

시작 크기 용도
———————————————————————–
0000000000000000 0000007fffffffff 512GB 유저

ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc

ffffffbbffff0000 ffffffbbffffffff  64KB [guard page]

ffffffbc00000000 ffffffbdffffffff   8GB vmemmap

ffffffbe00000000 ffffffbffbbfffff  ~8GB [guard, 추후 vmmemap]

ffffffbffa000000 ffffffbffaffffff  16MB PCI I/O 공간

ffffffbffb000000 ffffffbffbbfffff  12MB [guard]

ffffffbffbc00000 ffffffbffbdfffff   2MB 고정 맵핑

ffffffbffbe00000 ffffffbffbffffff   2MB [guard]

ffffffbffc000000 ffffffbfffffffff  64MB 모듈들

ffffffc000000000 ffffffffffffffff 256GB 커널 논리 메모리 맵


64KB 페이지의 AArch64 리눅스 메모리 배치:

시작 크기 용도
———————————————————————–
0000000000000000 000003ffffffffff   4TB 유저

fffffc0000000000 fffffdfbfffeffff  ~2TB vmalloc

fffffdfbffff0000 fffffdfbffffffff  64KB [guard page]

fffffdfc00000000 fffffdfdffffffff   8GB vmemmap

fffffdfe00000000 fffffdfffbbfffff  ~8GB [guard, 추후 vmmemap]

fffffdfffa000000 fffffdfffaffffff  16MB PCI I/O 공간

fffffdfffb000000 fffffdfffbbfffff  12MB [guard]

fffffdfffbc00000 fffffdfffbdfffff   2MB 고정 맵핑

fffffdfffbe00000 fffffdfffbffffff   2MB [guard]

fffffdfffc000000 fffffdffffffffff  64MB 모듈들

fffffe0000000000 ffffffffffffffff   2TB 커널 논리 메모리 맵


4KB 페이지의 변환 테이블 탐색:

+——–+——–+——–+——–+——–+——–+——–+——–+
|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
+——–+——–+——–+——–+——–+——–+——–+——–+
 |                 |         |         |         |         |
 |                 |         |         |         |         v
 |                 |         |         |         |   [11:0]  페이지 내의 오프셋
 |                 |         |         |         +-> [20:12] L3 인덱스
 |                 |         |         +———–> [29:21] L2 인덱스
 |                 |         +———————> [38:30] L1 인덱스
 |                 +——————————-> [47:39] L0 인덱스 (미사용)
 +————————————————-> [63] TTBR0/1


64KB 페이지의 변환 테이블 탐색:

+——–+——–+——–+——–+——–+——–+——–+——–+
|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
+——–+——–+——–+——–+——–+——–+——–+——–+
 |                 |    |               |              |
 |                 |    |               |              v
 |                 |    |               |            [15:0]  페이지 내의 오프셋
 |                 |    |               +———-> [28:16] L3 인덱스
 |                 |    +————————–> [41:29] L2 인덱스 (38:29 만 사용)
 |                 +——————————-> [47:42] L1 인덱스 (미사용)
 +————————————————-> [63] TTBR0/1

KVM을 사용할 때, 하이퍼바이저는 커널 페이지를 EL2에서 커널 VA로부터 고정된
오프셋(커널 VA의 상위 24비트를 0으로 셋팅한)에 맵핑합니다:

시작 크기 용도
———————————————————————–
0000004000000000 0000007fffffffff 256GB HYP 내에서 맵핑된 커널 객체

[Linux:Kernel] AArch64 리눅스 부팅(AArch64 Linux Booting)

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).

Documentation/arm64/booting.txt

AArch64 리눅스 부팅

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

Author: Will Deacon <will.deacon@arm.com>
번역  : 양정석 <dasomoli@gmailREMOVETHIS.com>
Date  : 07 September 2012

이 문서는 Russell King의 ARM 부팅 문서에 기초하고 AArch64 리눅스 커널의
모든 공개 릴리즈와 연관됩니다.

AArch64 예외 모델은 몇 개의 예외 단계(EL0 – EL3)으로, 그 중 EL0와 EL1은
시큐어와 논-시큐어 구성을 가지는 것으로 구성되어 있습니다. EL2는
하이퍼바이저 단계이고 논-시큐어 모드에서만 존재합니다. EL3는 가장 높은
단계이고, 시큐어 모드에서만 존재합니다.

이 문서의 목적에 따라, 우리는 ‘부트 로더’ 용어를 간단히 리눅스 커널로
제어를 넘기기 전에 CPU(들) 상에서 실행되는 모든 소프트웨어로 정의하여
사용할 것입니다. 이것은 시큐어 모니터와 하이퍼바이저 코드를 포함할 것이고,
또는 최소 부팅 환경을 준비하기 위한 한 줌의 명령들이 될 수도 있습니다.

기본적으로, 부트 로더는 다음을 (최소한) 제공해야 합니다:

1. RAM을 셋업하고 초기화
2. 디바이스 트리를 셋업
3. 커널 이미지를 압축 해제
4. 커널 이미지를 호출
1. RAM을 셋업하고 초기화
————————

요구 사항: 필수

부트 로더는 커널이 시스템 상의 임시 데이터 저장 공간으로 사용할 모든
RAM을 찾아서 초기화할 것으로 여겨집니다. 이는 머신 의존적인 방법으로
수행됩니다. (자동으로 모든 RAM의 크기를 재고 위치시키는데 내부
알고리즘을 사용하거나, 머신 안의 RAM에 대한 지식을 사용하거나, 또는
부트 로더 설계자가 맞춰 보는 다른 방법을 사용할 수도 있습니다.)
2. 디바이스 트리를 셋업
———————–

요구 사항: 필수

디바이스 트리 조각 (dtb)는 8 바이트 경계로 커널 이미지의 시작으로부터
512 메가 바이트 내에, 그리고 2 바이트 경계에 걸치지 않도록 위치해야만
합니다. 이것은 커널이 초기 페이지 내이블 내의 하나의 섹션 맵핑을 사용해서
조각을 맵핑할 수 있도록 해줍니다.
3. 커널 이미지를 압축 해제
————————–

요구 사항: 선택

AArch64 커널은 현재 압축 해제기를 제공하지 않고, 그래서 압축된 Image 타겟
(예를 들면, Image.gz)이 사용된다면 부트 로더에 의한 압축 해제
(gzip, 기타 등)를 요구합니다. 이 요구 사항을 구현하지 않은 부트로더들을
위해서 압축되지 않은 Image 타겟이 현재 대신 이용 가능합니다.
4. 커널 이미지를 호출
———————

요구 사항: 필수

압축 해제된 커널 이미지는 다음과 같은 64바이트 헤더를 포함합니다:

  u32 code0;
/* 실행 가능 코드 */
  u32 code1; /* 실행 가능 코드 */
  u64 text_offset; /* 이미지 로딩 오프셋 */
  u64 res0 = 0; /* 여분으로 예약 */
  u64 res1 = 0; /* 여분으로 예약 */
  u64 res2 = 0; /* 여분으로 예약 */
  u64 res3 = 0; /* 여분으로 예약 */
  u64 res4 = 0; /* 여분으로 예약 */
  u32 magic = 0x644d5241; /* 매직 넘버, 리틀 엔디언, “ARM\x64” */
  u32 res5 = 0;       /* 여분으로 예약 */
헤더 설명:

– code0/code1 은 stext로의 뜀을 책임집니다.
– EFI를 통해 부팅할 때, code0/code1은 초기에 건너 뜁니다. res5는
  PE 헤더로의 offset이고, PE 헤더는 EFI 진입 포인트(efi_stub_entry)를
  가집니다. 그 코드 조각이 작업을 끝내면, 보통의 부팅 프로세스를 재개하기
  위해서 code0 로 점프합니다.
  
이미지는 시스템 RAM의 시작으로부터 지정된 오프셋(현재는 0x80000)에
위치하고, 거기서 호출되어야만 합니다. 시스템 RAM의 시작은 2MB로 정렬되어져
있어야 합니다.

커널로 점프하기 전에, 다음 조건을 만족해야만 합니다:

– 모든 DMA 가능 장치들을 중지시켜 메모리가 가짜 네트워크 패킷이나
  디스크 데이터로 인해 깨지지 않도록 하세요. 이것은 많은 디버깅 시간을
  절약시켜 줄 것입니다.
  
– 주요 CPU 일반-목적(general-purpose) 레지스터 셋팅
  x0 = 시스템 RAM 내의 디바이스 트리 조각(dtb)의 물리 주소
  x1 = 0 (차후 용도를 위해 예약)
  x2 = 0 (차후 용도를 위해 예약)
  x3 = 0 (차후 용도를 위해 예약)  
  
– CPU 모드
  모든 형태의 인터럽트는 PSTATE.DAIF(Debug, Serror, IRQ 그리고 FIQ)로
  마스킹되어져야 합니다.
  CPU는 EL2(가상화 확장에 접근하기 위해서 추천함) 또는 논-시큐어 EL1 에
  있어야 합니다.

– 캐시, MMU
  MMU는 반드시 꺼져야 합니다.
  명령 캐시는 켜지거나 꺼져 있을 수 있습니다.
  로딩된 커널 이미지에 해당하는 주소 범위는 PoC로 깨끗해야 합니다.
  시스템 캐시나 켜진 캐시와 연관된 다른 마스터들의 존재 안에서,
  이것은 보통, 셋/웨이 연산보다는 VA에 의한 캐시 관리를 필요로 합니다.
  VA 연산에 의한 구조화된 캐시 관리를 준수하는 시스템 캐시는 설정되어져야
  하고, 켜지게 될 것 입니다.
  VA 연산에 의한 구조화된 캐시 관리를 따르지 않는(권장하지 않음) 시스템
  캐시는 설정되고 꺼져야만 합니다.

– 구조화된 타이머
  CNTFRQ는 반드시 타이머 주기로 프로그램되어야 하고, CNTVOFF는 모든
  CPU들의 일관된 값으로 프로그램되어야 합니다. 만약 EL1에서 커널로
  진입한다면, CNTHCTL_EL2는 반드시 셋팅된 EL1PCTEN(비트 0)을 가져야 합니다.

– 연관성
  커널에 의해 부팅될 모든 CPU들은 커널로의 진입 상의 같은 연관 도메인의
  일부가 되어야 합니다. 이것은 각 CPU 상의 관리 연산의 수신을 켜는
  ‘구현에 따라 정의된’ 초기화를 요구할 것입니다.
  
– 시스템 레지스터
  커널이미지가 진입하는 그 예외 레벨에서 모든 쓰기 가능한 구조화된 시스템
  레지스터들은 ‘알려지지 않은’ 상태 내의 실행을 막기 위해서 더 높은 예외
  레벨에서 소프트웨어에 의해 초기화되어야만 합니다.

위에 쓰여진 CPU 모드, 캐시, MMU, 구조화된 타이머, 연관성과 시스템 레지스터들에
대한 요구사항은 모든 CPU에 적용됩니다. 모든 CPU는 같은 예외 레벨 안에서
커널로 진입해야 합니다.

부트로더는 각 CPU가 다음과 같은 관례로 커널로 진입할 것으로 생각합니다:

– 주 CPU는 커널 이미지의 첫 명령으로 직접 점프해야만 합니다. 이 CPU에 의해
  넘겨진 디바이스 트리 조각은 각 CPU 노드의 ‘enable-method’ 프로퍼티를
  포함해야만 합니다. 지원되는 enable-method 들은 아래에서 설명합니다.

  부트로더는 이들 디바이스 트리 프로퍼티를 생생하고 커널 진입보다 먼저
  조각 안에 그들을 끼워 넣을 것입니다.

– “spin-table” enable-method 의 CPU들은 그들의 cpu 노드 내에
  하나의 ‘cpu-release-addr’ 프로퍼티를 가져야 합니다. 이 프로퍼티는
  자연스럽게 정렬된 64비트의 0으로 초기화된 메모리 위치를 나타냅니다.

  이 CPU들은 예약된 영역 안에 포함되어야만 하는, 그들의 cpu-release-addr
  위치를 폴링하는 (디바이스 트리 안의 /memreserve/ 영역에 의해 커널로
  전달되는) 메모리의 예약된 영역 안의 커널 밖에서 돌아야 합니다.
  wfe 명령은 비지-루프(busy-loop)의 부하를 줄이기 위해서 추가될 것이고,
  sev는 주 CPU에 의해 일어날 것입니다. cpu-release-addr에 의해
  가리켜지는 위치를 읽는 것이 0이 아닌 값을 반환할 때, 그 CPU는 이 값으로
  점프해야 합니다. 그 값은 하나의 64비트 리틀 엔디언 값으로 쓰여질
  것이므로 CPU들은 읽은 값을 그리로 점프하기 전에 그들 원래의 엔디언으로
  변환해야 합니다.

– “psci” enable method의 CPU들은 커널의 밖(즉, memory 노드 안에 커널로
  기술된 메모리의 그 영역 밖, 또는 디바이스 트리 안의 /memreserve/ 영역에
  의해 커널로 기술된 메모리의 예약된 영역 안)에 남아 있어야 합니다.
  커널은 커널 내로 CPU들을 가져오기 위해서 ARM DEN 0022A
  (“Power State Coordination Interface System Software on ARM processors”)
  문서 안에 설명된 것처럼 CPU_ON 호출들을 일으킬 것입니다.
  
  디바이스 트리는 하나의 ‘psci’ 노드를
  Documentation/devicetree/bindings/arm/psci.txt 안에 설명된대로
  포함해야만 합니다.

– 두번째 CPU 일반-목적 레지스터 셋팅
  x0 = 0 (차후 용도를 위해 예약)
  x1 = 0 (차후 용도를 위해 예약)
  x2 = 0 (차후 용도를 위해 예약)
  x3 = 0 (차후 용도를 위해 예약)

[Android] “Running Android with low RAM” 의 Kernel Configuration

Except as noted, this content is licensed under Creative Commons Attribution 2.5. For details and restrictions, see the Content License.
 

원문: http://source.android.com/devices/low-ram.html
번역: 양정석<dasomoli@gmailREMOVETHIS.com>(근데 원래 혼자 보려던 거라 이상한 거 많음;;)

커널 설정


직접 회수(Direct reclaim)를 줄이기 위한 커널/ActivityManager 튜닝

직접 회수는 하나의 프로세스 또는 커널이 메모리의 한 페이지를 (직접 혹은 새로운 페이지 안의 폴트로 인해서) 할당하고자 하며, 커널이 모든 사용 가능한 자유 메모리를 사용하고 있을 때 일어납니다. 이것은 커널에게 하나의 페이지를 해제하는 동안 할당을 막도록 요구합니다. 결국 이것은 더티한 File-backed 페이지를 플러싱하기 위한 디스크 I/O나 lowmemorykiller가 프로세스 하나를 죽이기를 기다리는 것을 종종 요구합니다. 이것은 UI 스레드를 포함하는 어떤 스레드에 추가 I/O를 일으킬 수 있습니다.
직접 회수를 피하기 위해서 커널은 kswapd나 백그라운드 회수를 촉발시키는 워터마크를 가집니다. 이것은 페이지들을 해제하도록 시도해서 다음에 그를 할당하는 리얼 타임 스레드가 빨리 수행할 수 있도록 하는 하나의 스레드입니다.
백그라운드 회수를 촉발시키는 디폴트 임계값은 2GB 디바이스에서 2MB, 512MB 디바이스에서 636KB로, 상당히 낮습니다. 그리고 커널은 그저 수 MB의 메모리를 백그라운드 회수 시에 회수할 뿐입니다. 이것은 수 MB 이상을 빨리 할당하는 어떤 프로세스는 빨리 직접 회수를 치게 될 것이라는 것을 의미합니다.
새로운 커널에 튜닝 가능한 지원이 android-3.4 커널 브랜치에 패치 92189d47f66c67e5fd92eafaa287e153197a454f(“add extra free kbytes tunable”)로 추가됩니다. 이 패치를 디바이스의 커널로 체리픽하는 것은 ActivityManager가 커널에게 3개의 풀스크린 32 bpp 버퍼의 메모리를 자유롭게 유지하도록 할 것임을 이야기하는 것을 허용할 것입니다.
이들 임계값은 프레임워크 config.xml을 통해 설정될 수 있습니다.
<!– 커널 내에 (존재한다면) 튜닝 가능한 /proc/sys/vm/extra_free_kbytes를 셋팅하는 디바이스 설정. 높은 값은 커널이 free를 유지하는 메모리의 양을 증가시키고, 할당 시간을 줄이고, lowmemerykiller가 더 빨리 죽이도록 할 것입니다. 낮은 값은 프로세스들에 의해 더 많은 메모리를 사용하도록 하지만 디스크 I/O나 lowmemorykiller 상에서의 대기를 막는 더 많은 할당이 일어날 것입니다. 화면 크기에 기초한 ActivityManager에 의해 선택된 기본 값은 덮어씌움. 0은 커널의 기본 값을 넘는 추가 메모리를 유지하는 것을 막습니다. -1은 기본값을 유지합니다 –>
<integer name=”config_extraFreeKbytesAbsolute”>-1</integer>
<!– 커널 내에 (존재한다면) 튜닝 가능한 /proc/sys/vm/extra_free_kbytes를 조정하는 디바이스 설정. 0은 ActivityManager가 고르는 기본 값을 사용합니다. 양수 값은 커널이 해제를 유지하는 메모리의 양을 증가시키고, 할당 시간을 줄이고, lowmemorykiller 가 더 빨리 죽이도록 할 것입니다. 음수 값은 프로세스들에 의해 사용되는 메모리를 더 많이 허용하지만, 디스크 I/O나 lowmemorykiller 상의 대기를 막는 더 많은 할당이 일어날 것입니다. 화면 크기에 기초한 ActivityManager에 의해 선택된 기본 값은 직접 더해짐. –>
<integer name=”config_extraFreeKbytesAdjust”>0</integer>
LowMemoryKiller 튜닝
ActivityManager는 각 우선 순위 단계 버킷 안에서 프로세스를 실행하는데 필요한 file-backed 페이지(캐시된(cached) 페이지)의 워킹 셋의 그 예상치를 맞추기 위해서 LowMemoryKiller의 임계값을 설정합니다. 디바이스가 워킹 셋을 위한 높은 요구 사항을 갖는다면, 예를 들면, 벤더 UI가 더 많은 메모리를 요구하거나 더 많은 서비스가 추가되었다면, 임계값은 증가될 수 있습니다.
작아지고 있는 캐시 때문에 디스크 스레싱(thrashing)이 일어나기 전에 백그라운드 프로세스들이 죽여지고 있어서, 너무 많은 메모리가 file backed 페이지를 위해 예약되어 지고 있다면 임계값을 줄일 수 있습니다. 
<!– 커널 내의 lowmemorykiller 내의 튜닝 가능한 minfree를 셋팅하는 디바이스 설정. 높은 값은 lowmemorykiller가 더 일찍 켜지고, 파일 캐시 안에 더 많은 메모리를 유지하고, I/O 스레싱을 막도록 할 것이지만, 메모리 내에 더 적은 프로세스가 머물도록 할 것입니다. 낮은 값은 더 많은 프로세스가 메모리 상에 유지되지만, 너무 낮으면 스레싱을 일으킬 것입니다. 화면 크기와 가장 큰 lowmemorykiller 버킷을 위한 전체 메모리에 기초해서 ActivityManager에 의해 선택된 기본값을 덮어쓰고, 더 작은 버킷에 비례해서 크기가 조정됨. -1은 기본값을 유지 —>
<integer name=”config_lowMemoryKillerMinFreeKbytesAbsolute”>-1</integer>
<!– 커널 내의 lowmemorykiller 내의 튜닝 가능한 minfree를 조정하는 디바이스 설정. 높은 값은 lowmemorykiller가 더 일찍 켜지고, 파일 캐시 안에 더 많은 메모리를 유지하고, I/O 스레싱을 막도록 할 것이지만, 메모리 내에 더 적은 프로세스가 머물도록 할 것입니다. 낮은 값은 더 많은 프로세스가 메모리 상에 유지되지만, 너무 낮으면 스레싱을 일으킬 것입니다. 화면 크기와 가장 큰 lowmemorykiller 버킷을 위한 전체 메모리에 기초해서 ActivityManager에 의해 선택된 기본값에 직접 더해지고, 더 작은 버킷에 비례해서 크기가 조정됨. 0은 기본값을 유지 —>
<integer name=”config_lowMemoryKillerMinFreeKbytesAdjust”>0</integer>

Framework의 설정 참고 소스 코드: frameworks/base/services/java/com/android/server/am/ProcessList.java

[Linux:Kernel] 왜 “volatile” 타입 클래스가 쓰이지 않는 것이 좋을까

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).
Documentation/volatile-considered-harmful.txt
번역: 양정석<dasomoli@gmailREMOVETHIS.com>
왜 “volatile” 타입 클래스가 쓰이지 않는 것이 좋은가
—————————————————
C 프로그래머들은 종종 volatile을 그 변수가 현재 스레드의 실행 밖에서 바뀔 수
있다는 의미로 사용합니다; 그 결과, 그들은 가끔 커널 코드 안에서 공유 자료
구조들을 사용할 때 이를 사용하고자 합니다. 다른 말로 하면, 그들은 간단한
atomic 변수의 일종처럼, 그게 아닌데도, volatile 형식을 다루는 것으로 알고
있습니다. volatile 커널 코드의 용도는 거의 절대 맞지 않습니다; 이 문서는 그
이유를 설명합니다.
volatile에 대한 이해를 위한 핵심은 그 목적이 거의 아무도 절대 진정으로 원하지
않는 최적화를 막기 위해서라는 것입니다. 커널 안에서, 누군가는 공유되는
자료 구조를 매우 다른 태스크의 원치 않는 동시 접근으로부터 보호해야 합니다.
원치 않는 동시성에 대한 보호 처리는 또한 거의 모든 최적화에 관련된 문제를 더
효율적인 방법으로 피할 것입니다.
volatile처럼, 자료로 안전하게 동시 접근을 하는 커널 기본 요소(스핀락(spinlock),
뮤텍스(mutex), 메모리 장벽(memory barrier), 기타 등등)는 원치 않는 최적화를
막도록 설계되었습니다. 그들이 적절히 사용된다면, 그들은 volatile을 사용할
필요가 없을 것입니다. volatile이 여전히 필요하다면, 거기에는 거의 확실히 코드
어딘가에 버그가 있습니다. 적절히 작성된 커널 코드 안에서 volatile은 오직
느리게만 만들 것입니다.
일반적인 커널 코드 블록을 생각해 봅시다:
    spin_lock(&the_lock);
    do_something_on(&shared_data);
    do_something_else_with(&shared_data);
    spin_unlock(&the_lock);
모든 코드가 락킹(locking) 규칙을 따른다면, shared_data의 값은 the_lock이 잡힌
동안, 예기치 않게 바뀔 수 없습니다. 그 자료를 가지고 놀고 싶어 할 어떤 다른
코드는 락 상에서 대기할 것입니다. 스핀락 기본 요소는 자료 접근이 그들을
가로지르는 최적화가 되지 않을 것임을 의미하는 메모리 장벽처럼 – 그들은
명시적으로 그렇게 하도록 작성되었습니다 – 동작합니다. 그래서 컴파일러는 그것이
shared_data 안에 있을 것을 안다고 생각할 수도 있지만. spin_lock() 호출이 메모리
장벽처럼 동작한 이후에는, 컴파일러가 알고 있는 어떠한 것도 잊어버리도록 강제할
것입니다. 거기에는 그 자료로의 접근에 대한 최적화 문제는 없을 것입니다.
shared_data가 volatile로 선언되었어도, 락킹은 여전히 필요할 것입니다.
그러나 컴파일러 역시, 우리가 다른 누구도 그것으로 무언가 할 수 없음을 알 때,
크리티컬 섹션 _안에서는_ shared_data로의 접근에 대한 최적화가 막혔으면 할
것입니다. 락이 잡힌 동안, shared_data는 volatile이 아닙니다. 공유된 자료로
뭔가 할 때, 적절한 락킹은 – 잠재적으로 해로운 – volatile을 불필요하게 만들 것
입니다.
volatile 저장 클래스는 근본적으로 메모리-매핑된(memory-mapped) I/O 레지스터들을
위해 의미가 있습니다. 커널 안에서 레지스터 접근 역시 락으로 보호돼야 합니다만,
누군가는 또한 컴파일러가 크리티컬 섹션 안에서 레지스터 접근을 “최적화하는 것”을
원하지 않습니다. 그러나 커널 안에서, I/O 메모리 접근은 언제나
접근자(accessor) 함수를 통해 이루어집니다; I/O 메모리에 포인터를 통해 직접
접근하는 것은 얼굴이 찡그려지고, 모든 아키텍처에서 작동하지 않습니다.
이들 접근자는 원치 않는 최적화를 막도록 작성되었습니다. 그래서, 역시,
volatile은 불필요합니다.
누군가가 volatile을 사용하고자 하는 또 다른 상황은 프로세서가 한 변수의 값을
위해 바쁜-기다림(busy-waiting)을 할 때입니다. 바쁜 기다림을 수행하는 옳은
방법은:
    while (my_variable != what_i_want)
        cpu_relax();
cpu_relax() 호출은 CPU 전력 소비를 낮출 수 있고, 하이퍼 스레드 된 다른
프로세서에 양보할 수 있습니다; 또한 컴파일러 장벽처럼 서비스하는 일이
일어납니다. 그래서, 역시, volatile은 불필요합니다. 물론, 바쁜 기다림은
일반적으로 시작하는 반사회적 행동입니다.
volatile이 커널 안에서 이해되는 적은 수의 드문 상황들이 여전히 있습니다:
  – 직접 I/O 메모리 접근이 동작하는 아키텍처에서는 위에서 설명된 접근자
    함수들이 volatile을 사용할 수 있습니다. 기본적으로, 각 접근자 호출은
    그 자체로 작은 크리티컬 섹션이 되고, 접근이 프로그래머가 의도한 대로
    일어남을 보장합니다.
  – 메모리를 변경하는, 그렇지만 다른 보이는 부수 효과(side effect)나, GCC에 의해
    제거되는 위험 없는 인라인 어셈블리 코드. volatile 키워드를 asm 문장에
    추가하는 것은 이 제거를 막을 것입니다.
  – jiffies 변수는 그것이 참조되는 순간마다 다른 값을 가지지만, 어떤 특별한
    락킹도 없이 읽힐 수 있어서 특별합니다. 그래서 jiffies는 volatile일 수
    있지만, 이 타입의 다른 변수들의 추가는 강하게 얼굴이 찌푸려집니다.
    jiffies는 이런 점에서 (리누스의 말로) “멍청한 유산” 이슈로 생각됩니다; 이를
    고치는 것은 그 가치보다 더 많은 문제를 일으킬 수 있습니다.
  – 가끔 합법적으로 volatile이 될 수 있는 I/O 장치에 의해 수정될 수 있는
    일관적인(coherent) 메모리 안의 자료 구조로의 포인터. 네트워크 어댑터가 어떤
    기술자(descriptor)가 처리되었는지를 나타내기 위해 포인터를 수정하는 데서,
    그 어댑터에 의해 사용되는 링 버퍼가 이런 종류 상황의 한 예제입니다.
코드 대부분에서, volatile의 적용을 위한 위의 타당한 이유가 없습니다. 그 결과,
volatile의 사용은 버그처럼 보이고, 코드에 추가적인 정밀 조사를 가져오도록 할
가능성이 큽니다. volatile을 사용하고자 하는 개발자들은 발걸음을 돌리고 그들이
정말로 하고자 하는 바에 대해서 생각해 봐야 할 것입니다.
volatile 변수들의 제거 패치는 – 그들이 동시성 이슈들을 적절히 생각했음을
보여주는 타당한 이유로 다가오는 만큼 – 일반적으로 환영받습니다.
참고
—-
[1] http://lwn.net/Articles/233481/
[2] http://lwn.net/Articles/233482/
언급해야 할 이름
—————-
원래의 자극과 연구는 Randy Dunlap에 의해
작성은 Jonathan Corbet에 의해
의견을 통한 개선은 Satyam Sharma, Johannes Stezenbach, Jesper
Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
Richter로부터.
한국어 번역은 양정석이.