Last week, I focused on collapsing huge pages and swap in/out. Rik have asked me some questions and I countinue to reply them. When we study, he puts some hints to questions and sometimes, I back to old questions and try to understand them better. I've started to follow linux-mm list and understand what they mention about at least :). Before I've tried to follow some staging lists but see emails a lot* everyday.
My project includes very small coding according to other kernel internship projects but the topic is too complex and its about core functionality of Linux Kernel. That's really good :). Before the internship, I was thinking "I should pick a small staging driver and study for todo issues". Because with small driver, learning and to be part of Linux Kernel can be easier and I was going to do just self study, also work at another company so have not enough time. Todays, I study on almost hardest topic with a Linux Kernel developer!
I can start coding for my project but need to discuss which policy we will follow to get swapped out pages to memory. We should discuss about trade off to collapsing pages in a 2 mb page when getting them from swap to memory. Keeping in mind the functions is a bit hard for me, I re-look a lot of time to which function what does. My memory is not good :(.
I've replied following questions which are asked me by my mentor. When I reply the questions, don't need to search just from books, look to codes and understand a bit of them :).
Following call chains for Linux Kernel - 3.18
1) How is a page swapped out?
add_to_swap()
get_swap_page()
scan_swap_map()
if(PageTransHuge(page))
if (split_huge_page_to_list(page, list))
swapcache_free()
add_to_swap_cache()
Swapped out is implemented by add_swap_page(). The function allocates swap space for a page. Swap areas includes slots, and their size are equals to page frames.
It checks whether page up to date and locked then gets swap page, get_swap_page() firstly checks is there a swap page with atomic_long_read(&nr_swap_pages) if so, decrements nr_swap_pages by one. In there used highhest_bit to decrease searching time of free slot. get_swap_page() returns type swap_entry_t. add_swap_page(), cheks whether the page is huge, if so; it splits the huge page to list with
split_huge_page_to_list(page, list). The function calls __split_huge_page() -> __split_huge_page_map().
If split_huge_page_to_list() returns 0, that means splitted pages succesfully. After that it adds the page entry to swap cache. If huge page can not splitted then called swapcache_free(entry), to release retrieved swap page.
Note: I did not understand why we set page as dirty? at line:202. The page is not changed. Rik's answer: After the page is added to the swap, it is removed from the process page tables.
Then we have a page that is only in the page cache, and not mapped in any process. The dirty bit indicates the data has to be saved to swap before the page can be freed.
scan_swap_map() is used to find free swap slot.
2) Where is the information of where a page is in swap, stored in the data structures used to track the memory of a process? In other words, how does swap in find where in swap memory is?
Using swap_info_struct swap_info[] array, it includes indexes of ptes and also offsets are stored in swap_map.
3) How is a page swapped in?
do_swap_page()
pte_to_swp_entry()
lookup_swap_cache()
if (!page)
swapin_readahead()
else if (PageHWPoison(page)) {...}
It calls pte_to_swp_entry(), pte is converted to swap entry. the function converts pte to architecture independent entry format. Then checks validation of entry with non_swap_entry(). Sets DELAYACCT_PF_SWAPIN flag to spcefiy that does in swap operation. It checks whether the page in swap cache. If so, checks HWPoison flag which is for recovering memory errors; if not runs swapin_readahead() to get probably needs to swap in pages. If HWPoison is setted, it goes to label out_release and release the page and swap cache page from page cache. I've a question here: if the page was huge, but right now it is not because splitted to locate on swap. The page have no compound flag anymore? Is that correct?
Rik's answer: Swap only ever stores single pages, indeed. That means swapped
in pages will not have the compound flag set page_cache_release() calls put_page(), and the function checks using PageCompound().
Note: do_swap_page() gets two pte argument. orig_pte is created by handle_mm_fault() using ACCESS_ONCE(). The macro is for volatile issues maybe but I didn't understand why second pte is created.
Answer: do_swap_page gets both the location of the pte (a pointer) and the value of the pte at handle_mm_fault time. This way it can verify whether the pte changed from its original value, while it is doing things (like retrieving data from swap)
4) How can you discover whether a page is present in the swap cache?
_PAGE_FILE detects whether the page in swap cache, it is into page table entry.
5) Under what conditions are 4kB pages collapsed into a 2MB THP?
In handle_pte_fault(), at line: 3219 do_swap_page() is called because system want to swapped in pages, so it wants to collapse the pages but it can't. This happens, if the cases occur: pte shouldn't be on memory and swap cache. Also pte should be belong to anonymous page, not to file.
Rik's question: Can you write down the call traces that contain the collapse functions in mm/huge_memory.c?
My answer, there are two cases for it:
do_huge_pmd_anonymous_page() -> alloc_hugepage_vma() -> .. __alloc_pages_nodemask()
khugepaged_scan_pmd() -> collapse_huge_page() -> khugepaged_alloc_page() -> alloc_pages_exact_node() -> .. -> __alloc_pages_nodemask()
Rik's answer: Firt call chain, you can leave alone during your project, and is important to understand what the data structures look like.
Second call chain: This is the one you will want to work with.
6) how many pages would be good to bring into swap when trying to collapse a huge page? how many is too much?
x86 systems use 4kB page size. It can be enlarged maximum 4mb. With 2mb page, it is enlarged 512 times, thats good. 4mb page means 1024 times enlarged, it is not so good, if size is more than 4mb huge page, it will be useless.
Rik's answer: Sure, but if all of them are swapped out, it is obviously a bad
idea to bring them all into memory just to collapse them into a 2MB THP.
Out of the 512 pages, what would be a reasonable number to not be in memory already, and bring in from swap? 1? 5? 10? 20? What would the number depend on?
My answer: do_swap_page() -> swapin_readahead() -> swapin_nr_pages()
In swapin_nr_pages(), using page_cluster it detects how many pages getting swap in.
page_cluster defined in swap.c. swap_setup() function assigns its default value.
7) what about pages that are already in the swap cache? how should we count those?
For this question, I'm a bit confused, thought swap cache is a swap slot .. and replied different thing :). Firstly, I've tried to count how many pages in swap, afterwards go ahead to correct intent.
If a page in the swap cache, that means the page up to date on memory. Also the page is on the one swap slot. Swap cache size is equal to a swap slot. struct swap_info_struct, it has array swap_map.
I've read from book, swap_duplicate() increases slot usagecounter, probably it mentions about the line:
count = p->swap_map[offset];
I've seen on comment line of the function "increment its swap map count." So I guess, swap_map count can be slot usage counter. But I know swap_info struct per swap area not per swap slot. A swap area can include set of slots, so I think, swap_map count doesn't mean swap cache usage counter. Did I misunderstand? Can you inform me about swap_map?
Rik's answer: The swap_map counter means the number of users of that swap slot, which may be different from the number of users of the swap cache page.
However, this line of research is tangential to your project, and your interpretation of question 2 differs from my intent.
My answer: I've thought, when a page will be added to swap cache, it increases count of swap cache page.
add_to_swap_cache() -> __add_to_swap_cache()
In __add_to_swap_cache(), after adding radix tree, it increases the counter at line 104:
address_space->nrpages++;
nrpages specify total number of pages in address_space which stores swap cache address that means how many pages are in swap cache.
8) what about the !pte_write test in __collapse_huge_page_isolate? how can that break collapsing of a THP? is there a simple way to improve that?
pte_present() checks whether the entry have write access. It needs to create a page using page table entry with vm_normal_page(). If write access is disallowed, can't create page.
My mentor said __collapse_huge_page_isolate() is important point your project, and I've reviewed it:
__collapse_huge_page_isolate()
for (_pte = pte; _pte < pte+HPAGE_PMD_NR; _pte++, address += PAGE_SIZE) {
pte_none()
!pte_present() || !pte_write()
isolate_lru_page(page)
For loop:
Firstly, it checks pte_none(), this function returns true if pte is not in Ram. There is a counter none, checks with none for allowed khugepaged_max_ptes_none. If exceeds the limit then goes to label out. pte_none() returns true if none of the bits in the pte are set, that is the pte is all zeroes. pte_present() also is used for page swapped out. pte_write() checks whether the kernel write to page. Then checks is the page compound, if so does system halt. If page is not anon nor swap backed then does system halt. The page should have only one reference, this property checked by _count variable. Then it locks the page.
I'm looking isolate_lru_page(), Lru list includes inactive file/page, active file/page. But I didn't understand why there is PG_lru flag and we check it with PageLRU(page) at line 1344, vmscan.c
Rik's answer: If the page is not currently on an LRU, a different task may have that page on a pagevec, and do something with it later. That could race with trying to collapse the hugepage, and cause all sorts of problems.
In isolate_lru_page(), it checks again VM_BUG_ONE(!page_count(page), page), but already it checked for page_count() before calling isolate_lru_page() line at: 2171. Why it does this again?
Rik's answer: The page_count check is debugging code, in case somebody changes the kernel and calls isolate_lru_page on a page that got freed. It checks PageLRU once outside the lock (it can be changed by another CPU), and once inside the lock (taking a lock is expensive, and only done conditionally).
And also it checks PageLRU two times, in isolate_lru_page(). It gets lruvec then runs page_lru(), which checks page unevictable, if so sets lru as unevictable; if not, calls page_lru_base_type(), this decides base type for page - file or anon after adds active property and returns lru. Then isolate function runs get_page(), if page head or normal, increments _count. Then clear page lru and calls del_page_from_lru_list(), this function deletes lru from page using list_del()
It checks for page young conditions, then set referenced as 1. If it goes to label out, it runs release_pte_pages().
Note: That function gets a pointer to the start of a page table page, and iterates over all the ptes inside that page table page. A 2MB THP contains 512 4kB pages, which is 1<<HPAGE_PMD_ORDER pages.
31 Aralık 2014 Çarşamba
23 Aralık 2014 Salı
Begining to Read Memory Management Codes
My Linux Kernel internship started two weeks ago and will take 3 months. My mentor is Rik Van Riel. My project aim to fix transparent huge page swapping issues, if system needs to swap huge pages, it has to split the pages to small sized ones but then the system can not reconstitute the huge pages.
Rik asked me some questions about huge page and swapping and I've replied them. Before the reply the questions I've looked for following data structures and definitions.
Firstly I've started to examine struct page and mm_struct in mm_types.h. The kernel holds all information in mm_struct, it includes vm_area_struct *mmap which involves list of memory areas. vm_areas_struct is an object to show memory areas. Also, the kernel threads don't use mm_struct so if you see if (!mm) {...} it means this is kernel thread.
Likely & Unlikely Functions: Theese are for branch prediction so used for compiler optimization. They supply to guess which instruction will run and do read ahead.
http://kernelnewbies.org/FAQ/LikelyUnlikely
http://stackoverflow.com/questions/109710/likely-unlikely-macros-in-the-linux-kernel
Numa & Uma Systems: I've understood the two keywords looking the picture :).
Hot & Cold Page: If a page in cpu cache, it is hot page however cold page is vice versa.
struct scan_control: It is used for page scaning, holds following variables:
unsigned long nr_scanned: How many inactive pages were scanned.
int may_writepage: It determines whether the kernel can write backing store.
swap_cluster_max: It is restriction for a lru list.
struct zone: The kernel divides memory to nodes, and the nodes include zone lists. Every zone area include pages. You can look for struct zone.
struct list_head: Doubly linked list, to build & manage lists.
Page Flags: http://lxr.free-electrons.com/source/include/linux/page-flags.h
High Memory: Linux Kernel seperate high rate of memory for user space so high memory means user space.
http://unix.stackexchange.com/questions/4929/what-are-high-memory-and-low-memory-on-linux
Page Vector: Provides operations on page list instead of individual pages.
Slot: Swap area is divided to slots. Size of each slot equals to page frame.
up_read/write, down_read/write functions: They are for spinlock issues and includes assembly instructions.
BUG_ON* functions: Checks given condition and returns system halt or nothing.
http://lxr.free-electrons.com/source/include/linux/mmdebug.h#L18
Swap Cache: Some pages after swapped out, if the page is not changed, it has an entry on swap cache and system can read data on memory withouth get the page to back memory.
http://www.linux-tutorial.info/modules.php?name=MContent&pageid=314
Transparent Huge Page vs. Huge Page: Transparent huge page supplies a layer for huge page. http://goo.gl/qGksYX
Note-1: Swap space used by user space tools (mkswap)
Note-2: x86 systems don't use pte level for THP (transparent huge page), it can direct access data on pmd.
Following questions which are asked to me by my mentor. I've explained just important points for my project and their function traces because there are a lot of functions, sometimes they can be very complex :).
Below call chains for Linux Kernel - 3.18
1) from do_page_fault(), sometimes the VM uses transparent huge pages
(2MB size on x86) for anonymous memory. What functions does the
code go through between do_page_fault() and the function that
installs 2MB pages in the process page tables?
When I examined functions, I saw a lot of spinlock functions and Rik said, they for ensure that multiple concurrent instances of the page fault code do not manipulate the page table simultaneously.
do_page_fault()
__do_page_fault() /* checks the fault is belong to bad area or good area */
handle_mm_fault()
__handle_mm_fault()
__do_huge_pmd_anonymous_page()
pgtable_trans_huge_withdraw takes a page table page from the process's
reserve of page table pages, so the 2MB page (mapped at pmd level) can
be mapped as 4kB page entries (at the pte level).
2) When are 2MB pages used?
If PAE is enabled, then use 2mb pages. I've looked for it following links:
http://en.wikipedia.org/wiki/Physical_Address_Extension https://www.cs.rutgers.edu/~pxk/416/notes/09a-paging.html
http://en.wikipedia.org/wiki/Page_Size_Extension
http://en.wikipedia.org/wiki/Page_%28computer_memory%29#Huge_pages
3) What does the VM do when a 2MB page cannot be allocated?
(still in memory.c and huge_memory.c)
In do_huge_pmd_anonymous_page(), if it can not allocate 2MB page;
it returns, out of memory or fall back. It also calls count_vm_event()
with THP_FAULT_FALLBACK argument. At line: 824, it tries to set
huge zero page, if it can't do that, calls put_huge_zero_page(),
which calls atomic_dec_and_test().
At line: 839: If it couldn't install huge page, it calls
put_page(). I've thought;in put_page, it checks whether
the page compound or not, but the page will be compound
always, because the page comes from alloc_hugepage_vma().
4) When the system runs low on memory and wants to swap something
out, it will split up a huge page before assigning it space in
a swap area. Find the code in vmscan.c, swapfile.c and huge_memory.c
that does that. What does the function trace look like from
try_to_free_pages to the function that splits the huge pages?
try_to_free_pages()
throttle_direct_reclaim(gfp_ mask, zonelist, nodemask)
do_try_to_free_pages(zonelist, &sc)
delayacct_freepages_start()
global_reclaim()
do while { vmpressure_prio()
shrink_zones() /* if a zone reclaimable it returns true */}
I've seperated shrink_zones() to below:
shrink_zones()
nodes_clear(shrink.nodes_to_ scan)
loop:
populated_zone() {return (!!zone->present_pages);}
zone_reclaimable_pages(zone) -> get_nr_swap_pages()
node_set()
zone_reclaimable()
shrink_zone()
shrink_lruvec()
shrink_list()
shrink_active_list()
shrink_inactive_list()
shrink_page_list()
add_to_swap()
split_huge_page_to_list()
__split_huge_page()
__split_huge_page_map()
try_to_free_pages(): If memory is not sufficent, it checks pages and removes least used one.
shrink_zones(): It is runned by kswapd with specified time interval and used for remove rarely used
pages. It also balances inactive and active lists using shrink_active_list().
shrink_active_list(): Provides to transfer pages between active_list and inactive_list and detect least used active lists and also implements page selection.
shrink_inactive_list(): Removes lists from inactive_list and send the lists to shrink_page_list().
In general, shrink_* functions run per zone.
5) in huge_memory.c look at collapse_huge_page and the functions
that call it - under what conditions does the kernel gather up
512 4kB pages and collapse them into one 2MB page?
collapse_huge_page()
khugepaged_alloc_page() /* allocate new page */
__collapse_huge_page_isolate( vma, address, pte); /* this one is new function for me */
if (isolate_lru_page(page)) { ... }
if (pte_young(pteval) || PageReferenced(page) ||
mmu_notifier_test_young(vma-> vm_mm, address)) { ... }
__collapse_huge_page_copy()
collapse_huge_page_isolate() removes pages from lru with isolate_lru_page().
I've thought: when collapsing pages, their lru's will change. So it isolates
pages.
Note-1: __collapse_huge_page_copy(): The 4kB pages could be anywhere in memory.
The 2MB page needs to be one contiguous page.
That means the contents of the 4kB pages need
to be copied over into the one 2MB page.
khugepaged_scan_pmd(), if page is young, it will call collapse_huge_page().
If the collapse function can correct vma, pmd and isolate pages, it collapses
pages.
6) under what conditions does the kernel decide not to collapse
the 4kB pages in a 2MB area into a 2MB page?
There some conditions for it:
1) If can't alloc khuge page, it won't collapse.
2) I've looked to this condition in collapse_huge_page():
if (unlikely(khugepaged_test_ exit(mm))) {goto out;}
if mm has no user, it goes to label out and doesn't collapse pages.
3) If it can't find vma and pmd
4) If it can't isolate pages
7) look at what happens when shrink_page_list()
passes a 2MB transparent huge page to add_to_swap()
with it".
The second pmd_populate puts in place the page table page containing
the 4kB pages that map the 2MB area.
Rik asked me some questions about huge page and swapping and I've replied them. Before the reply the questions I've looked for following data structures and definitions.
Firstly I've started to examine struct page and mm_struct in mm_types.h. The kernel holds all information in mm_struct, it includes vm_area_struct *mmap which involves list of memory areas. vm_areas_struct is an object to show memory areas. Also, the kernel threads don't use mm_struct so if you see if (!mm) {...} it means this is kernel thread.
Likely & Unlikely Functions: Theese are for branch prediction so used for compiler optimization. They supply to guess which instruction will run and do read ahead.
http://kernelnewbies.org/FAQ/LikelyUnlikely
http://stackoverflow.com/questions/109710/likely-unlikely-macros-in-the-linux-kernel
Hot & Cold Page: If a page in cpu cache, it is hot page however cold page is vice versa.
struct scan_control: It is used for page scaning, holds following variables:
unsigned long nr_scanned: How many inactive pages were scanned.
int may_writepage: It determines whether the kernel can write backing store.
swap_cluster_max: It is restriction for a lru list.
struct list_head: Doubly linked list, to build & manage lists.
Page Flags: http://lxr.free-electrons.com/source/include/linux/page-flags.h
High Memory: Linux Kernel seperate high rate of memory for user space so high memory means user space.
http://unix.stackexchange.com/questions/4929/what-are-high-memory-and-low-memory-on-linux
Page Vector: Provides operations on page list instead of individual pages.
Slot: Swap area is divided to slots. Size of each slot equals to page frame.
up_read/write, down_read/write functions: They are for spinlock issues and includes assembly instructions.
BUG_ON* functions: Checks given condition and returns system halt or nothing.
http://lxr.free-electrons.com/source/include/linux/mmdebug.h#L18
Swap Cache: Some pages after swapped out, if the page is not changed, it has an entry on swap cache and system can read data on memory withouth get the page to back memory.
http://www.linux-tutorial.info/modules.php?name=MContent&pageid=314
Transparent Huge Page vs. Huge Page: Transparent huge page supplies a layer for huge page. http://goo.gl/qGksYX
Note-1: Swap space used by user space tools (mkswap)
Note-2: x86 systems don't use pte level for THP (transparent huge page), it can direct access data on pmd.
Following questions which are asked to me by my mentor. I've explained just important points for my project and their function traces because there are a lot of functions, sometimes they can be very complex :).
Below call chains for Linux Kernel - 3.18
1) from do_page_fault(), sometimes the VM uses transparent huge pages
(2MB size on x86) for anonymous memory. What functions does the
code go through between do_page_fault() and the function that
installs 2MB pages in the process page tables?
When I examined functions, I saw a lot of spinlock functions and Rik said, they for ensure that multiple concurrent instances of the page fault code do not manipulate the page table simultaneously.
do_page_fault()
__do_page_fault() /* checks the fault is belong to bad area or good area */
handle_mm_fault()
__handle_mm_fault()
__do_huge_pmd_anonymous_page()
pgtable_trans_huge_withdraw takes a page table page from the process's
reserve of page table pages, so the 2MB page (mapped at pmd level) can
be mapped as 4kB page entries (at the pte level).
2) When are 2MB pages used?
If PAE is enabled, then use 2mb pages. I've looked for it following links:
http://en.wikipedia.org/wiki/Physical_Address_Extension https://www.cs.rutgers.edu/~pxk/416/notes/09a-paging.html
http://en.wikipedia.org/wiki/Page_Size_Extension
http://en.wikipedia.org/wiki/Page_%28computer_memory%29#Huge_pages
3) What does the VM do when a 2MB page cannot be allocated?
(still in memory.c and huge_memory.c)
In do_huge_pmd_anonymous_page(), if it can not allocate 2MB page;
it returns, out of memory or fall back. It also calls count_vm_event()
with THP_FAULT_FALLBACK argument. At line: 824, it tries to set
huge zero page, if it can't do that, calls put_huge_zero_page(),
which calls atomic_dec_and_test().
At line: 839: If it couldn't install huge page, it calls
put_page(). I've thought;in put_page, it checks whether
the page compound or not, but the page will be compound
always, because the page comes from alloc_hugepage_vma().
4) When the system runs low on memory and wants to swap something
out, it will split up a huge page before assigning it space in
a swap area. Find the code in vmscan.c, swapfile.c and huge_memory.c
that does that. What does the function trace look like from
try_to_free_pages to the function that splits the huge pages?
try_to_free_pages()
throttle_direct_reclaim(gfp_
do_try_to_free_pages(zonelist, &sc)
delayacct_freepages_start()
global_reclaim()
do while { vmpressure_prio()
shrink_zones() /* if a zone reclaimable it returns true */}
I've seperated shrink_zones() to below:
shrink_zones()
nodes_clear(shrink.nodes_to_
loop:
populated_zone() {return (!!zone->present_pages);}
zone_reclaimable_pages(zone) -> get_nr_swap_pages()
node_set()
zone_reclaimable()
shrink_zone()
shrink_lruvec()
shrink_list()
shrink_active_list()
shrink_inactive_list()
shrink_page_list()
add_to_swap()
split_huge_page_to_list()
__split_huge_page()
__split_huge_page_map()
try_to_free_pages(): If memory is not sufficent, it checks pages and removes least used one.
shrink_zones(): It is runned by kswapd with specified time interval and used for remove rarely used
pages. It also balances inactive and active lists using shrink_active_list().
shrink_active_list(): Provides to transfer pages between active_list and inactive_list and detect least used active lists and also implements page selection.
shrink_inactive_list(): Removes lists from inactive_list and send the lists to shrink_page_list().
In general, shrink_* functions run per zone.
5) in huge_memory.c look at collapse_huge_page and the functions
that call it - under what conditions does the kernel gather up
512 4kB pages and collapse them into one 2MB page?
collapse_huge_page()
khugepaged_alloc_page() /* allocate new page */
__collapse_huge_page_isolate(
if (isolate_lru_page(page)) { ... }
if (pte_young(pteval) || PageReferenced(page) ||
mmu_notifier_test_young(vma->
__collapse_huge_page_copy()
collapse_huge_page_isolate() removes pages from lru with isolate_lru_page().
I've thought: when collapsing pages, their lru's will change. So it isolates
pages.
Note-1: __collapse_huge_page_copy(): The 4kB pages could be anywhere in memory.
The 2MB page needs to be one contiguous page.
That means the contents of the 4kB pages need
to be copied over into the one 2MB page.
khugepaged_scan_pmd(), if page is young, it will call collapse_huge_page().
If the collapse function can correct vma, pmd and isolate pages, it collapses
pages.
6) under what conditions does the kernel decide not to collapse
the 4kB pages in a 2MB area into a 2MB page?
There some conditions for it:
1) If can't alloc khuge page, it won't collapse.
2) I've looked to this condition in collapse_huge_page():
if (unlikely(khugepaged_test_
if mm has no user, it goes to label out and doesn't collapse pages.
3) If it can't find vma and pmd
4) If it can't isolate pages
passes a 2MB transparent huge page to add_to_swap()
When it sent 2 MB page to add_to_swap function, it firstly checks whether page locked and up to date then calls get_swap_page(). If there is no swap page returns 0, If not it checks transHugePAge() then implements split_huge_page_to_list(). In split_huge_page_to_list it gets anonymous vma and does write-lock for it and checks PageCompound. With PageCompound it controls the is huge or not. Then it checks PageSwapBacked. Then calls __split_huge_page() and the function wants the page shouldn't be tail and splits the page in __split_huge_page_splitting(). The function backs to add_to_swap and does swapcache_free() issues.
8) Can you explains what the page looks like after it has been split?
What happened to the 2MB page? What do we have instead?
What happened with the PageCompound flag?
__split_huge_page(), it calls __split_huge_page_splitting() in the iteration. It counts number of mapped pmds before splitted it and increase mapcount.
In split_huge_page_map(), it takes page offset with address argument. Firstly, it checks pmd address validity. It
creates small entries in for loop with mk_pte(), set_pte_at(), pte_unmap (this one is just nop instruction for x86 systems). The for loop does one entry for page one, then page two, then page three etc. It changes address of entry adding pagesize (haddr += PAGE_SIZE) up to number of pmd.
I've asked, why pmd_populate() is performed two times at lines: 1790, 1843?
Rik's answer: The first pmd_populate puts in place a special transparent huge page
PMD that says "this transparent hugepage is being split, do not messwith it".
The second pmd_populate puts in place the page table page containing
the 4kB pages that map the 2MB area.
Note-1: In __split_huge_page() iterates vma from root of red black tree at line: 1864 but the function gets only one page and a page can match just one vma. So why it needs to iterate vma?
Rik replied my question: "The same page may be shared by multiple processes, if the
process that created the 2MB page originally called fork() afterwards."
Note-2: In __split_huge_page_splitting(), it calls pmdp_splitting_flush() what does it do also pmd_update and flush_tlb_range function? I think it should save pmd's content before splitting, it shouldn't lose it. Why it flushes pmd?
Rik's answer: if a small page is touched or dirtied afterwards, we want the MMU to set the accessed and/or dirty bit on the 4kB page entry.
Note-3: We can ignore PVOP_VCALL stuff - that is for Xen, which uses an alternate function for filling in page table info.
9) Under what conditions can a region with 4kB pages be
turned into a 2MB transparent huge page?
I've traced following call chain:
do_page_fault()
__do_page_fault()
handle_mm_fault()
__handle_mm_fault() /* check conditions */
do_huge_pmd_anonymous_page() /* check conditions */
__do_huge_pmd_anonymous_page() /* check conditions */
In __handle_mm_fault(), "if (pmd_none(*pmd) && transparent_hugepage_enabled( vma)) { ... }" if the expression is correct, it can realize do_huge_pmd_anonymous_page(). I've seen this quote for pmd_none() "if page is not in RAM, returns true." But I think, if page is not used for any process, it includes zeros and should be in RAM.
In do_huge_pmd_anonymous_page(), "if (!(flags & FAULT_FLAG_WRITE) && transparent_hugepage_use_zero_ page()) { ... }"
if it can correct the condition, it can start to create transparet huge page. I've looked for condition values.
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; allow retry and killable flag values are defined with special values (0x08, 0x02)?
I think their values only for to check something. And transparent_hugepage_flags is 0UL, is it always have this value? I've looked for its value,
probably always have same value. The last condition creates huge zero page using set_huge_zero_page() which calls pmd_mkhuge().
One more condition: __do_huge_pmd_anonymous_page( mm, vma, haddr, pmd, page), if it returns false, that means created transparent huge page at line: huge_memory.c#L808
If pmd_none() returns true, creates thp.
10) What code turns 4kB pages into a 2MB page?
pmd_mkhuge() installs 2 MB page. Actually, it does pmd_set_flags(pmd, _PAGE_PSE).
_PAGE_PSE uses _PAGE_BIT_PSE which means huge page.
11) Under what conditions can a region with 4kB pages not
be turned into a 2MB transparent huge page?
There are a lot conditions for this.
turned into a 2MB transparent huge page?
I've traced following call chain:
do_page_fault()
__do_page_fault()
handle_mm_fault()
__handle_mm_fault() /* check conditions */
do_huge_pmd_anonymous_page() /* check conditions */
__do_huge_pmd_anonymous_page() /* check conditions */
In __handle_mm_fault(), "if (pmd_none(*pmd) && transparent_hugepage_enabled(
In do_huge_pmd_anonymous_page(), "if (!(flags & FAULT_FLAG_WRITE) && transparent_hugepage_use_zero_
if it can correct the condition, it can start to create transparet huge page. I've looked for condition values.
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; allow retry and killable flag values are defined with special values (0x08, 0x02)?
I think their values only for to check something. And transparent_hugepage_flags is 0UL, is it always have this value? I've looked for its value,
probably always have same value. The last condition creates huge zero page using set_huge_zero_page() which calls pmd_mkhuge().
One more condition: __do_huge_pmd_anonymous_page(
If pmd_none() returns true, creates thp.
10) What code turns 4kB pages into a 2MB page?
pmd_mkhuge() installs 2 MB page. Actually, it does pmd_set_flags(pmd, _PAGE_PSE).
_PAGE_PSE uses _PAGE_BIT_PSE which means huge page.
11) Under what conditions can a region with 4kB pages not
be turned into a 2MB transparent huge page?
There are a lot conditions for this.
1) If the entire 2MB page inside vma, return fall back.
2) If it can't create anonymous vma, return out of memory.
3) If it can't create huge page vma, return fall back.
4) If it get true from __do_huge_pmd_anonymous_page() , return fall back.
5) in __do_huge_pmd_anonymous_page() , if page is not support huge page, the code create kernel panic, and halt.
VM_BUG_ON_PAGE(!PageCompound( page), page);
6) If it cannot allocate a huge page
2) If it can't create anonymous vma, return out of memory.
3) If it can't create huge page vma, return fall back.
4) If it get true from __do_huge_pmd_anonymous_page()
5) in __do_huge_pmd_anonymous_page()
VM_BUG_ON_PAGE(!PageCompound(
6) If it cannot allocate a huge page
Etiketler:
gezegen,
huge page,
internship,
kernel,
linux,
memory management,
opw,
swap,
thp
7 Aralık 2014 Pazar
Page Fault Handler
I've started to read something about memory issue. Firstly, I've looked for basic concepts for it. This link is pretty good for basic concepts.
MMU (Memory Management Unit) translates physical memory addresses to virtual addresses. It creates an interrupt when a page fault occured. When a process try to access an address and if the address is unknown for MMU then it creates page fault exception. In this case page fault exception handler examines current state of MMU and process. do_page_fault(...) function is page fault handler for Linux. It is processor specific function, I've studied for x86 based systems.
do_page_fault() function gets two arguments which are error code and registers of the process. The error code specifies the page fault whether because of read operation or write operation.
Firstly the function saves address of line which is cause of the exception (control register two), then saves prev state of process.
Page fault handler needs to detect whether the page fault is good or bad. Good page fault means the process needs more memory. Bad page fault can occur for different cases, in general it causes of terminate the process by the handler.
Actually do_page_fault calls __do_page_fault(...) function and it is main area to handle the page fault.
In Linux based systems every process has a page directory and page table. We can understand which pages used by which process with the data structures. If process needs more memory, the handler gets a page from pglist_data which is a global list and adds the page to page table of process.
The function using mm_struct can detect whether the process has permission access for the address. It uses find_vma function for this operation. If process has to access then the address assigned to the process else the process is terminated and segmentation fault occured.
Processes are created as instance of task_struct which includes mm_structs and keeps info about processes.
You can see process resources under /proc/pid/*. If you want to see process vma, then type "cat /proc/pid/maps" on bash. To understand memory issues better, I've read the chapter, this book is very good for kernel newbies.
Also this two links are very helpful for me, they are for kernel 2.6x series but very good to understand big picture of the topic.
Other sources:
http://www.stillhq.com/pdfdb/000446/data.pdf
http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/
MMU (Memory Management Unit) translates physical memory addresses to virtual addresses. It creates an interrupt when a page fault occured. When a process try to access an address and if the address is unknown for MMU then it creates page fault exception. In this case page fault exception handler examines current state of MMU and process. do_page_fault(...) function is page fault handler for Linux. It is processor specific function, I've studied for x86 based systems.
do_page_fault() function gets two arguments which are error code and registers of the process. The error code specifies the page fault whether because of read operation or write operation.
Firstly the function saves address of line which is cause of the exception (control register two), then saves prev state of process.
Page fault handler needs to detect whether the page fault is good or bad. Good page fault means the process needs more memory. Bad page fault can occur for different cases, in general it causes of terminate the process by the handler.
Actually do_page_fault calls __do_page_fault(...) function and it is main area to handle the page fault.
In Linux based systems every process has a page directory and page table. We can understand which pages used by which process with the data structures. If process needs more memory, the handler gets a page from pglist_data which is a global list and adds the page to page table of process.
The function using mm_struct can detect whether the process has permission access for the address. It uses find_vma function for this operation. If process has to access then the address assigned to the process else the process is terminated and segmentation fault occured.
Processes are created as instance of task_struct which includes mm_structs and keeps info about processes.
You can see process resources under /proc/pid/*. If you want to see process vma, then type "cat /proc/pid/maps" on bash. To understand memory issues better, I've read the chapter, this book is very good for kernel newbies.
Also this two links are very helpful for me, they are for kernel 2.6x series but very good to understand big picture of the topic.
Other sources:
http://www.stillhq.com/pdfdb/000446/data.pdf
http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/
Etiketler:
do_page_fault,
gezegen,
kernel,
linux,
memory,
mmu,
page fault handler
25 Kasım 2014 Salı
Linux Kernel Internship
Last month I've applied Gnome Outreach Program for Women and sent patches for Linux Kernel. I've applied it because wanted to learn low level things. I also really like computer design and architecture topics. Actually, I have not enough knowledge about them but like to learn them.
Linux Kernel Community accepted to me as an intern. I'll study on Khugepaged swap readahead project. Working with Linux Kernel team will be great experience for me. They really want to help kernel newbies :).
Actually, studying on Linux Kernel needs a lot reading. Just for writing a few code lines needs to read one chapter from one book, a few blog posts about topic and ask something to developers :).
Nowadays, I've started to read about memory management issues like TLB, Huge Pages, Page Fault from one operating system book and also examine do_page_fault() function.
Linux Kernel Community accepted to me as an intern. I'll study on Khugepaged swap readahead project. Working with Linux Kernel team will be great experience for me. They really want to help kernel newbies :).
Actually, studying on Linux Kernel needs a lot reading. Just for writing a few code lines needs to read one chapter from one book, a few blog posts about topic and ask something to developers :).
Nowadays, I've started to read about memory management issues like TLB, Huge Pages, Page Fault from one operating system book and also examine do_page_fault() function.
22 Kasım 2014 Cumartesi
Google Hiring Process
This story started 4 months ago. I've got an email from a Google recruiter. She wanted to do a phone conversation with me. I was very happy to hear this and accepted the conversation immediately.
First phone conversation was initial phone interview, she asked me basic questions about data structures, bitwise operations, linux commands etc. But I think the questions were not basic :p I passed initial phone interview and preferred Site Reliability System Engineer position for myself. I took first round telephone interview with an Google engineer and used Google Doc for coding questions.
Before the first round to prepare myself I was studying algorithms, data structures, network, linux commands, troubleshooting. Following links were really helpful for me:
Geeks For Geeks, Glassador, Careerup, Cracking Code Interviews, System Design, Devops Interview Questions.
I passed first round, the engineer said to me you did great most of this interview! I was really happy to hear this and couldn't believe what I heard :) The whole process was very excited, funny and nice for me.
We moved the process for second phone interview. Again I studied for same things and used Google Doc for coding questions. My second interview has only one question, when I replied the question, interviewer generated new questions which was derived from same question. Second round interview was not very good but my recruiter called me and said you passed it, we would like to invite you for onsite interview at one Google office, Google will pay your all expenses. I preferred Dublin office of Google which is headquarters for the Europe offices.
I prepared to practising English myself, and whole summer went English speaking courses, because in my country have no other chance to practising English unfortunately :(
Actually, my English is not very good and when talked with employees of Google I feel really excited so I couldn't talk much so many times :) however during the onsite interviews I discussed a lot on questions because it is my job, but for usual questions how are you?, are you excited?, do you have question? etc. this kind of questions I could talk less :) Engineers of Google are very understanding people to my English. Also in Google Dublin office, people coming from 65 different countries and there are 45 different languages.
Onsite interview have 5 different steps. For SRE (Site Reliability Engineer) position, I've got following steps and each step has 45 minutes with 5 different interviewers. Onsite interview is last round for Google hiring process.
1) Non Abstract Large System Design
2) Troubleshooting / Problem Solving
3) Practical Coding - Ruby
4) Design/Coding
5) Unix/ Linux Systems
Onsite interview questions were not expected things for me :(. I read a lot of blog posts, they say the questions are very expected, but I think some of them really expected things however most of them were not. I also solved a lot of onsite interview questions before mine.
I couldn't pass the onsite interview however this was really great experience for me. The whole process was very exciting, every steps made me very happy and excited :). I also met a few Google engineers and my recruiters. They are really helpful and friendly people.
Dublin is not big city so there is no a lot of people, it is not crowded. It was very rainy on my interview day. I stayed two nights in Dublin. After my interview I had time to discover the city. There is river which called as River Liffey in Dublin. It is like a map to find your road :p You can follow along the river so can find your hotel very quickly :).
I'm very happy to met with Google engineers. This was very good experience for me. I'm only 22 years old I can retry it, thanks a lot to Google.
First phone conversation was initial phone interview, she asked me basic questions about data structures, bitwise operations, linux commands etc. But I think the questions were not basic :p I passed initial phone interview and preferred Site Reliability System Engineer position for myself. I took first round telephone interview with an Google engineer and used Google Doc for coding questions.
Before the first round to prepare myself I was studying algorithms, data structures, network, linux commands, troubleshooting. Following links were really helpful for me:
Geeks For Geeks, Glassador, Careerup, Cracking Code Interviews, System Design, Devops Interview Questions.
I passed first round, the engineer said to me you did great most of this interview! I was really happy to hear this and couldn't believe what I heard :) The whole process was very excited, funny and nice for me.
We moved the process for second phone interview. Again I studied for same things and used Google Doc for coding questions. My second interview has only one question, when I replied the question, interviewer generated new questions which was derived from same question. Second round interview was not very good but my recruiter called me and said you passed it, we would like to invite you for onsite interview at one Google office, Google will pay your all expenses. I preferred Dublin office of Google which is headquarters for the Europe offices.
I prepared to practising English myself, and whole summer went English speaking courses, because in my country have no other chance to practising English unfortunately :(
Actually, my English is not very good and when talked with employees of Google I feel really excited so I couldn't talk much so many times :) however during the onsite interviews I discussed a lot on questions because it is my job, but for usual questions how are you?, are you excited?, do you have question? etc. this kind of questions I could talk less :) Engineers of Google are very understanding people to my English. Also in Google Dublin office, people coming from 65 different countries and there are 45 different languages.
Onsite interview have 5 different steps. For SRE (Site Reliability Engineer) position, I've got following steps and each step has 45 minutes with 5 different interviewers. Onsite interview is last round for Google hiring process.
1) Non Abstract Large System Design
2) Troubleshooting / Problem Solving
3) Practical Coding - Ruby
4) Design/Coding
5) Unix/ Linux Systems
Onsite interview questions were not expected things for me :(. I read a lot of blog posts, they say the questions are very expected, but I think some of them really expected things however most of them were not. I also solved a lot of onsite interview questions before mine.
I couldn't pass the onsite interview however this was really great experience for me. The whole process was very exciting, every steps made me very happy and excited :). I also met a few Google engineers and my recruiters. They are really helpful and friendly people.
Dublin is not big city so there is no a lot of people, it is not crowded. It was very rainy on my interview day. I stayed two nights in Dublin. After my interview I had time to discover the city. There is river which called as River Liffey in Dublin. It is like a map to find your road :p You can follow along the river so can find your hotel very quickly :).
I'm very happy to met with Google engineers. This was very good experience for me. I'm only 22 years old I can retry it, thanks a lot to Google.
14 Temmuz 2014 Pazartesi
Android Cihazlarda Rom Değiştirmek
Androidli telefonlarda yüklü olarak gelen rom dışında istediğimiz başka romları kurmak da mümkün. En bilinen romlar ise cynmod, miyui, aokp, paranoid android. Rom chip üzerindeki kalıcı yazılımları oluşturur. Romu değiştirerek cihazın içeriğini baştan sonra değiştirmiş olabiliriz. Bu değişim işlemci ve bellek kullanımı, kısayolları, ekran kilidi gibi birçok özelliği değiştirebilir. Telefondan aldığımız verimi artırabilir azaltabilir.
Ben şimdiye kadar cynmod'u denedim. Cihazınıza uygun cynmod romlarını buradan bulabilirsiniz. Uygun .zip dosyasını indirdikten sonra telefona sdcard içerisine kopyalamalıyız. adb reboot recovery diyerek telefonu recovery modda açıp zip dosyası kurmayı seçerek .zip'in konumunu da belirtmeliyiz. Cynmod'u kurduktan sonra Google Play Store sistemden kalkıyor. Play Store'u kurmak için gapps paketini indirmeliyiz. Gapps paketini de telefona kopyalayıp yine recovery moddan açarak kurulumu gerçekleştirmeliyiz.
Cihazın kendi sahipleri dışında bir firmanın yayınladığı romlara custom rom deniliyor. Cihaza kurulabilecek resmi (offical) romlara ise stock rom deniliyor. Custom rom kurduktan sonra stock romu indirerek tekrar cihazı ilk günkü haline çevirebiliriz.
Genelde stock romların içerisinde bir kurulum betiği oluyor. Nexus cihazlar için stock romlara buradan ulaşabilirsiniz. Nexus-5 için hammerhead .tgz dosyası içerisinde flash-all.sh dosyası var. İndridiğimiz .tgz dosyasını bilgisayarda açmalıyız. Cihazı ise adb reboot bootloader şeklinde fastboot modundan açarak bu dosyayı bilgisayardan çalıştırıp kurulumu gerçekleştirebiliriz.
Ben şimdiye kadar cynmod'u denedim. Cihazınıza uygun cynmod romlarını buradan bulabilirsiniz. Uygun .zip dosyasını indirdikten sonra telefona sdcard içerisine kopyalamalıyız. adb reboot recovery diyerek telefonu recovery modda açıp zip dosyası kurmayı seçerek .zip'in konumunu da belirtmeliyiz. Cynmod'u kurduktan sonra Google Play Store sistemden kalkıyor. Play Store'u kurmak için gapps paketini indirmeliyiz. Gapps paketini de telefona kopyalayıp yine recovery moddan açarak kurulumu gerçekleştirmeliyiz.
Cihazın kendi sahipleri dışında bir firmanın yayınladığı romlara custom rom deniliyor. Cihaza kurulabilecek resmi (offical) romlara ise stock rom deniliyor. Custom rom kurduktan sonra stock romu indirerek tekrar cihazı ilk günkü haline çevirebiliriz.
Genelde stock romların içerisinde bir kurulum betiği oluyor. Nexus cihazlar için stock romlara buradan ulaşabilirsiniz. Nexus-5 için hammerhead .tgz dosyası içerisinde flash-all.sh dosyası var. İndridiğimiz .tgz dosyasını bilgisayarda açmalıyız. Cihazı ise adb reboot bootloader şeklinde fastboot modundan açarak bu dosyayı bilgisayardan çalıştırıp kurulumu gerçekleştirebiliriz.
Etiketler:
adb,
android,
custom rom,
cyanogenmod,
fastboot,
gezegen,
stock rom
13 Temmuz 2014 Pazar
Android Cihaz Rootlamak
Android telefonlara birkaç farklı şekilde root (yetkili kullanıcı) hakları verebiliriz. Android cihazlarda root olmak ise unix temelli işletim sistemlerindeki süper kullanıcı ile aynı şey.
Telefonu farklı modlarda başlatabilmek için güç, ses kısma-açma gibi tuşlara farklı kombinasyonlarda basmamız gerekli. Bu kombinasyonlar telefonun marka-modeline göre değişebilir ve elimizi sürekli şöyle miydi, böyle miydi düşüncesiyle basılı tutmak biraz zor :). Bunun yerine "android-tools-adb" ve "android-tools-fastboot" paketlerini kurarak telefonu bilgisayardan yönetebiliriz.
Android cihazlara root hakları vermek marka-modele göre değişebilir. Bu konudaki araştırmaları telefonun marka-modeline göre yapmak daha iyi olabilir. Ben burada adb ile kurulumdan bahsedeceğim için modele göre pek değişeceğini sanmıyorum ancak söylemek gerekirse Nexus-5 cihaz üzerinde çalışıyorum.
Usb kabloyu bilgisayara usb debug modda ve geliştirici hakları ile bağlamalıyız. Geliştirici yetkisi root ile aynı şey değil. Bilgisayardan telefona gelecek dosyaları kabul ettiğimizi belirtmek gibi birkaç işlem için gerekli. Geliştirici haklarına "Ayarlar->Telefon Hakkında->" yolunu izleyip "İnşa Numarası"na 5-6 kere basarak elde edilir. Debug mod için ise "Ayarlar->Geliştirici Seçenekleri"nde usb debug modunu aktif etmeliyiz.
Adb ise bilgisayardan telefonu yönetmek için gerekli. Bilgisayarda "adb devices" yazarak makineye bağlı cihazları görebiliriz. "adb shell" ile telefona bağlanabiliriz. Makineye birkaç telefon bağlı ise hangi cihaza erişeceğimizi belirtmeliyiz. "adb shell" ile telefona eriştikten sonra bash komutları ile telefonu yönetebiliriz ancak kullanabildiğimiz komutlar çok kısıtlı. Komut çeşidini artırmak için telefona busybox'ı kurabiliriz (busybox kurulumu root haklarını gerektiriyor). adb pull ile dosyaları bilgisayara çekebilir, adb push ile telefondan bilgisayara dosya aktarabiliriz. Örneğin telefondaki data dizininin içerisini root hakları olmadan listeyemeyiz, adb ile telefona bağlıyken su yazarak komut satırında root yetkilerini alabiliriz. Adb'nin tam belgesine buradan ulaşabilirsiniz.
Fastboot ise telefonu güncellemek, farklı recovery .img dosyaları yüklemek, bootloaderı kiltleyip açmak için kullanılabilir. Fastbooot hakkında daha fazlası için buraya bakabilirsiniz.
Cwm Yükleme
Telefonda yedekleme yapma, bilgileri sıfırlama, kurulum yapma gibi işlemler için birkaç farklı araç var. Bunlardan biri Clock Work Recovery Mod (cwm). Cwm'yi kurmak için buradan bilgisayara .img dosyasını indirebiliriz. adb reboot bootloader ile telefonu fastboot modunda açarak fastboot flash recovery cwm.img şeklinde recovery modu kurmuş oluruz. Şuan cihaz fastboot modda olduğu için ses kısma tuşu ile recovery moda geçerek telefonu yeniden başlatmalıyız. Böylece cwm'yi recovery mod aracı olarak yüklemiş olduk.
Root Hakları Verme
Buradan superSu.zip dosyasını telefona kopyalayıp, telefonu adb reboot recovery şeklinde recovery modda açarak install from zip'i seçmeliyiz. .zip'i kopyaladığımız konuma gidip dosyayı seçersek kurulum tamamlanmış olacak ve aşağıdakine benzer bir çıktı görülecek. Eğer .zip'i sdcarda kopyaladıysak sdcard'ı seçtikten sonra o/, legacy/, obb/ dizinlerinden o/ olan dizini seçmeliyiz. Bu şekilde kurulum tamamlanmış oldu.
İndirdiğimiz .zip dosyasını incelersek içinde SuperSu.apk'sı dışında betikler var, bu betiklerle gereken ayarları yapıp, .apk'yı yüklemeyi gerçekleştiriyor.
Root yetkisi verdiğimizi anlamak için SuperSu uygulaması yüklenmiş mi diye bakmak yeterlidir. Her zaman Supersu .apk'sının sistemde var olması rootlamanın başarılı bir şekilde tamanlanmış olduğu anlamına gelmiyor. Bu yüzden daha iyi bir yöntem ise adb ile telefona bağlıyken su yazınca root hakları veriliyorsa işlem sorunsuz tamamlanmış demektir.
Telefonu farklı modlarda başlatabilmek için güç, ses kısma-açma gibi tuşlara farklı kombinasyonlarda basmamız gerekli. Bu kombinasyonlar telefonun marka-modeline göre değişebilir ve elimizi sürekli şöyle miydi, böyle miydi düşüncesiyle basılı tutmak biraz zor :). Bunun yerine "android-tools-adb" ve "android-tools-fastboot" paketlerini kurarak telefonu bilgisayardan yönetebiliriz.
Android cihazlara root hakları vermek marka-modele göre değişebilir. Bu konudaki araştırmaları telefonun marka-modeline göre yapmak daha iyi olabilir. Ben burada adb ile kurulumdan bahsedeceğim için modele göre pek değişeceğini sanmıyorum ancak söylemek gerekirse Nexus-5 cihaz üzerinde çalışıyorum.
Usb kabloyu bilgisayara usb debug modda ve geliştirici hakları ile bağlamalıyız. Geliştirici yetkisi root ile aynı şey değil. Bilgisayardan telefona gelecek dosyaları kabul ettiğimizi belirtmek gibi birkaç işlem için gerekli. Geliştirici haklarına "Ayarlar->Telefon Hakkında->" yolunu izleyip "İnşa Numarası"na 5-6 kere basarak elde edilir. Debug mod için ise "Ayarlar->Geliştirici Seçenekleri"nde usb debug modunu aktif etmeliyiz.
Adb ise bilgisayardan telefonu yönetmek için gerekli. Bilgisayarda "adb devices" yazarak makineye bağlı cihazları görebiliriz. "adb shell" ile telefona bağlanabiliriz. Makineye birkaç telefon bağlı ise hangi cihaza erişeceğimizi belirtmeliyiz. "adb shell" ile telefona eriştikten sonra bash komutları ile telefonu yönetebiliriz ancak kullanabildiğimiz komutlar çok kısıtlı. Komut çeşidini artırmak için telefona busybox'ı kurabiliriz (busybox kurulumu root haklarını gerektiriyor). adb pull ile dosyaları bilgisayara çekebilir, adb push ile telefondan bilgisayara dosya aktarabiliriz. Örneğin telefondaki data dizininin içerisini root hakları olmadan listeyemeyiz, adb ile telefona bağlıyken su yazarak komut satırında root yetkilerini alabiliriz. Adb'nin tam belgesine buradan ulaşabilirsiniz.
Fastboot ise telefonu güncellemek, farklı recovery .img dosyaları yüklemek, bootloaderı kiltleyip açmak için kullanılabilir. Fastbooot hakkında daha fazlası için buraya bakabilirsiniz.
Cwm Yükleme
Telefonda yedekleme yapma, bilgileri sıfırlama, kurulum yapma gibi işlemler için birkaç farklı araç var. Bunlardan biri Clock Work Recovery Mod (cwm). Cwm'yi kurmak için buradan bilgisayara .img dosyasını indirebiliriz. adb reboot bootloader ile telefonu fastboot modunda açarak fastboot flash recovery cwm.img şeklinde recovery modu kurmuş oluruz. Şuan cihaz fastboot modda olduğu için ses kısma tuşu ile recovery moda geçerek telefonu yeniden başlatmalıyız. Böylece cwm'yi recovery mod aracı olarak yüklemiş olduk.
Root Hakları Verme
Buradan superSu.zip dosyasını telefona kopyalayıp, telefonu adb reboot recovery şeklinde recovery modda açarak install from zip'i seçmeliyiz. .zip'i kopyaladığımız konuma gidip dosyayı seçersek kurulum tamamlanmış olacak ve aşağıdakine benzer bir çıktı görülecek. Eğer .zip'i sdcarda kopyaladıysak sdcard'ı seçtikten sonra o/, legacy/, obb/ dizinlerinden o/ olan dizini seçmeliyiz. Bu şekilde kurulum tamamlanmış oldu.
İndirdiğimiz .zip dosyasını incelersek içinde SuperSu.apk'sı dışında betikler var, bu betiklerle gereken ayarları yapıp, .apk'yı yüklemeyi gerçekleştiriyor.
Root yetkisi verdiğimizi anlamak için SuperSu uygulaması yüklenmiş mi diye bakmak yeterlidir. Her zaman Supersu .apk'sının sistemde var olması rootlamanın başarılı bir şekilde tamanlanmış olduğu anlamına gelmiyor. Bu yüzden daha iyi bir yöntem ise adb ile telefona bağlıyken su yazınca root hakları veriliyorsa işlem sorunsuz tamamlanmış demektir.
19 Mayıs 2014 Pazartesi
Linux Kernel Geliştiriciliği İçin Bir Fırsat Daha! - Eudyptula-Challenge
Bir süredir Linux Kernel'a nasıl devam edebilirim diye düşünüyordum. Opw'ye katıldığım zamanlar Coccinelle, Sparse ve checkpatch.pl ile yama gönderdim. Bunun dışında smatch var ama smatch ile test yaparak aldığımız hataları çözmek biraz kafa karıştırıcı. Belki bir süre bir şeyler okumuş olmayı gerektiriyor.
Linux Kernel ile ilgili temel kavramlar var. Rcu'lar, birkaç fonksiyon, birkaç makro bunların hepsini okuyup yama göndermeye devam etmeliyim diye düşünmüştüm. Çekirdekle ilgili şeyleri okuduğumuzda hemen anlamak zor aslında oldukça zor gibi. Hatta insanlar bloglarında "artık çekirdek kodlarını anlayabiliyorum!" şeklinde yazılar paylaşıyorlar :) Bu şekilde ne yapsam diye düşünürken geçtiğimiz ay burada eudyptula-challenge sürecini gördüm.
Bu sürece başlamak için "little at eudyptula-challenge.org" adresine e-posta gönderip katılmak istediğimizi belirtmek yeterli. Peki bu süreç nasıl işliyor? E-posta yoluyla uzaktan bir çalışma gerçekleştiriliyor. Tüm e-postalarımızı otomatikleştirilmiş betikler cevaplıyor. Geliştiriciler ile etkileşim içinde bir çalışma değil. Eğer betiğe parse edemeyeceği ya da nasıl çalışıyorsa uygun bir cevap döndüremeyeceği bir soru ya da yapmamızı istediği dışında bir cevap atarsak bu betik e-postamızı geliştiricilere yönlendiriyor. Geliştiriciler ise birkaç gün içinde cevaplıyorlar ancak mümkün olduğunca geliştiricileri bu süreçle uğraşmak zorunda bırakmadan cevaplar göndermeliyiz.
Bu süreç 20 tane görevden oluşuyor. Temel "Hello World" driverından karmaşık driverlar yazmaya kadar ilerliyor. Gönderdiğimiz cevapları html, base64 gibi formatlarda göndermemeliyiz, çünkü betik parse edemiyor. Bir de genelde dosya eki şeklinde göndermemiz gerekiyor. Tarayıcıdan gmail'den göndermek problem oluşturur diye mutt kullanarak cevap atıyorum.
Bense henüz 5. görevdeyim :) Betik biraz yavaş cevap atıyor, şu an bu sürece 4000+ başvuran var. Bir saat içerisinde cevap attığım göreve bir hafta sonra "Bu görevi geçtiniz." e-postası aldım. Bu yüzden süreç biraz yavaş ilerliyor. Bir de bu süreçte yaptıklarımızı github, blog gibi bir yerlerde yazmamalıyız. Çünkü diğer başvuranlar "kopyala-yapıştır" yapmasınlar diye betik bize en başta belirtiyor ve bize bir id veriyor, cevapları bu id ile gönderiyoruz. Çekirdek için çok fazla yazılmış belge var, 3.10 sürümünde Documentation dizini çekirdek deposunun %4'ünü oluşturuyordu. Bu kadar belge arasından kaybolmadan çalışabilmek biraz zor. Belki bunu görebilmek için bir yerlere yazmayın diyorlar.
Aslında bu muhteşem bir fırsat. Tüm görevleri tamamlayamasak bile bir sürü şey öğrenmiş oluruz. İlk dört süreç aşırı temel. 5. süreçte usb driverları ile ilgili işler yapmak gerekiyor. Sonrasını henüz görmedim :).
Çekirdek geliştiricileri de kendini bu işe verebilecek yeni insanlar arıyorlar. Gerçekten çok büyük bir emek gerektiriyor. Ben meslek olarak değil ama sevdiğim ve kendimi geliştirmek için bir fırsat olarak gördüğüm için başvurdum.
Bu süreçte bir süre kısıtlaması ve acele yok. İstediğiniz zaman görevi tamamlayıp cevabı betiğe gönderebilirsiniz. Ortada bir challenge da yok. Sadece görevleri tamamladıkça cevap atmak ve yeni görevi beklemek yeterli.
Eudyptula-challenge'ın resmi sayfasına buradan ulaşabilirsiniz.
Linux Kernel ile ilgili temel kavramlar var. Rcu'lar, birkaç fonksiyon, birkaç makro bunların hepsini okuyup yama göndermeye devam etmeliyim diye düşünmüştüm. Çekirdekle ilgili şeyleri okuduğumuzda hemen anlamak zor aslında oldukça zor gibi. Hatta insanlar bloglarında "artık çekirdek kodlarını anlayabiliyorum!" şeklinde yazılar paylaşıyorlar :) Bu şekilde ne yapsam diye düşünürken geçtiğimiz ay burada eudyptula-challenge sürecini gördüm.
Bu sürece başlamak için "little at eudyptula-challenge.org" adresine e-posta gönderip katılmak istediğimizi belirtmek yeterli. Peki bu süreç nasıl işliyor? E-posta yoluyla uzaktan bir çalışma gerçekleştiriliyor. Tüm e-postalarımızı otomatikleştirilmiş betikler cevaplıyor. Geliştiriciler ile etkileşim içinde bir çalışma değil. Eğer betiğe parse edemeyeceği ya da nasıl çalışıyorsa uygun bir cevap döndüremeyeceği bir soru ya da yapmamızı istediği dışında bir cevap atarsak bu betik e-postamızı geliştiricilere yönlendiriyor. Geliştiriciler ise birkaç gün içinde cevaplıyorlar ancak mümkün olduğunca geliştiricileri bu süreçle uğraşmak zorunda bırakmadan cevaplar göndermeliyiz.
Bu süreç 20 tane görevden oluşuyor. Temel "Hello World" driverından karmaşık driverlar yazmaya kadar ilerliyor. Gönderdiğimiz cevapları html, base64 gibi formatlarda göndermemeliyiz, çünkü betik parse edemiyor. Bir de genelde dosya eki şeklinde göndermemiz gerekiyor. Tarayıcıdan gmail'den göndermek problem oluşturur diye mutt kullanarak cevap atıyorum.
Bense henüz 5. görevdeyim :) Betik biraz yavaş cevap atıyor, şu an bu sürece 4000+ başvuran var. Bir saat içerisinde cevap attığım göreve bir hafta sonra "Bu görevi geçtiniz." e-postası aldım. Bu yüzden süreç biraz yavaş ilerliyor. Bir de bu süreçte yaptıklarımızı github, blog gibi bir yerlerde yazmamalıyız. Çünkü diğer başvuranlar "kopyala-yapıştır" yapmasınlar diye betik bize en başta belirtiyor ve bize bir id veriyor, cevapları bu id ile gönderiyoruz. Çekirdek için çok fazla yazılmış belge var, 3.10 sürümünde Documentation dizini çekirdek deposunun %4'ünü oluşturuyordu. Bu kadar belge arasından kaybolmadan çalışabilmek biraz zor. Belki bunu görebilmek için bir yerlere yazmayın diyorlar.
Aslında bu muhteşem bir fırsat. Tüm görevleri tamamlayamasak bile bir sürü şey öğrenmiş oluruz. İlk dört süreç aşırı temel. 5. süreçte usb driverları ile ilgili işler yapmak gerekiyor. Sonrasını henüz görmedim :).
Çekirdek geliştiricileri de kendini bu işe verebilecek yeni insanlar arıyorlar. Gerçekten çok büyük bir emek gerektiriyor. Ben meslek olarak değil ama sevdiğim ve kendimi geliştirmek için bir fırsat olarak gördüğüm için başvurdum.
Bu süreçte bir süre kısıtlaması ve acele yok. İstediğiniz zaman görevi tamamlayıp cevabı betiğe gönderebilirsiniz. Ortada bir challenge da yok. Sadece görevleri tamamladıkça cevap atmak ve yeni görevi beklemek yeterli.
Eudyptula-challenge'ın resmi sayfasına buradan ulaşabilirsiniz.
Etiketler:
coccinelle,
eudyptula challenge,
gezegen,
kernel,
linux,
mutt,
ozgur yazilim,
sparse
9 Mayıs 2014 Cuma
Eskişehir Devfest Student Etkinliği
Geçtiğimiz hafta Eskişehir Anadolu Üniversitesi'nde Devfest Student etkinliği düzenlendi. Etkinliğe ben, Aybüke, Gülşah ve Necdet hoca birlikte katıldık.
Etkinlikte Aybüke ve Gülşah Opw sürecinden bahsettiler. Ben de Ruby & Gtk3 ile masaüstü uygulamalar yazmaktan bahsettim. 3 Mayıs'ta İstanbul ve Denizli'de de başka etkinlikler düzenlediğinden katılım oldukça azdı. Etkinlikte yaptığım konuşmanın sunumuna buradan ulaşabilirsiniz.
Sunum sonrası elbette şehri gezdik :). Üst dönemlerden Serhat Ersel bize şehri gezdirdi. Serhat'ı daha önceden okuduğum eğlenceli blog yazılarından ve tweetlerinden tanıyordum, aynı zamanda Serhat da öğrenciyken Necdet hoca ile çalışıyormuş.
Eskişehir birçok heykel barındıran, hareketli bir şehir ve aynı zamanda başka şehirlerden gezmeye gelen insanlarla dolup taşıyor diyebilirim. Gerçekten de gezilip görülmesi gereken bir şehir. Şehirde bizi misafir ettiğinden Serhat'a teşekkürler.
Etkinlikte Aybüke ve Gülşah Opw sürecinden bahsettiler. Ben de Ruby & Gtk3 ile masaüstü uygulamalar yazmaktan bahsettim. 3 Mayıs'ta İstanbul ve Denizli'de de başka etkinlikler düzenlediğinden katılım oldukça azdı. Etkinlikte yaptığım konuşmanın sunumuna buradan ulaşabilirsiniz.
Sunum sonrası elbette şehri gezdik :). Üst dönemlerden Serhat Ersel bize şehri gezdirdi. Serhat'ı daha önceden okuduğum eğlenceli blog yazılarından ve tweetlerinden tanıyordum, aynı zamanda Serhat da öğrenciyken Necdet hoca ile çalışıyormuş.
Eskişehir birçok heykel barındıran, hareketli bir şehir ve aynı zamanda başka şehirlerden gezmeye gelen insanlarla dolup taşıyor diyebilirim. Gerçekten de gezilip görülmesi gereken bir şehir. Şehirde bizi misafir ettiğinden Serhat'a teşekkürler.
6 Mayıs 2014 Salı
Latex ile Belge Hazırlama
Latex, işaretleme dili kullanılarak belge ya da sunum hazırlamak için kullanılan bir araç. Latex ile yazdığımız belgeleri pdf ve birkaç değişik biçime çevirebiliriz.
Latex'i ilk 2. sınıftayken Necdet hocanın önerisi üzerine kullanmıştım :). Latex ile belge hazırlarken matematiksel ifadeleri, şekilleri çok rahat sağlayabiliriz. .tex dosyalarını terminalden parametreler vererek istediğimiz biçime çevirebileceğimiz gibi, Latex için yazılmış arayüzleri, hazır şablonları da kullanabiliriz.
Bugünlerde cv hazırlamak için Latex kullanmam gerekti. Libre Office writer ya da Google Doc'da belge hazırlarken içeriğin yerleşimi zor oluyor ve uğraştırıyor. En ufak bir satır eklediğimizde içeriğin kalan kısmının yerleşimini bozuyor, aslında bunlarla uğraşmamak için Latex kullandım.
Latex'in birçok etiketinin ne olduğunu şimdilerde pek hatırlamıyorum :). 2. sınıftan sonra unutmuşum haliyle. Bu yüzden hazırladığım belgenin hepsini elle yazmadım, hazır şablonlardan birini seçip, beğenmediğim yerleri değiştirdim.
Latex'i ilk kullandığım zamanlarda konsoldan çalıştırıyordum. Ancak bu ara pek vaktim olmadığından, bir de çıktıyı hızlı bir şekilde görebilmek için texworks editörünü kullandım. Texworks çok güzel ve kullanımı rahat bir araç. Dosyada yaptığımız değişiklikleri yanda hemen görebiliyoruz.
Latex için hazır şablonlara buradan ulaşabilirsiniz.
Latex'i ilk 2. sınıftayken Necdet hocanın önerisi üzerine kullanmıştım :). Latex ile belge hazırlarken matematiksel ifadeleri, şekilleri çok rahat sağlayabiliriz. .tex dosyalarını terminalden parametreler vererek istediğimiz biçime çevirebileceğimiz gibi, Latex için yazılmış arayüzleri, hazır şablonları da kullanabiliriz.
Bugünlerde cv hazırlamak için Latex kullanmam gerekti. Libre Office writer ya da Google Doc'da belge hazırlarken içeriğin yerleşimi zor oluyor ve uğraştırıyor. En ufak bir satır eklediğimizde içeriğin kalan kısmının yerleşimini bozuyor, aslında bunlarla uğraşmamak için Latex kullandım.
Latex'in birçok etiketinin ne olduğunu şimdilerde pek hatırlamıyorum :). 2. sınıftan sonra unutmuşum haliyle. Bu yüzden hazırladığım belgenin hepsini elle yazmadım, hazır şablonlardan birini seçip, beğenmediğim yerleri değiştirdim.
Latex'i ilk kullandığım zamanlarda konsoldan çalıştırıyordum. Ancak bu ara pek vaktim olmadığından, bir de çıktıyı hızlı bir şekilde görebilmek için texworks editörünü kullandım. Texworks çok güzel ve kullanımı rahat bir araç. Dosyada yaptığımız değişiklikleri yanda hemen görebiliyoruz.
28 Nisan 2014 Pazartesi
Muğla Özgür Yazılım Semineri - 2014
Bu yıl yine Muğla Sıtkı Koçman Üniversitesi'nde özgür yazılımlar hakkında konuşmak için gittik. İlk konuşmayı Necdet hoca yaptı. Sonrasında ben "Bilgisayar Mühendisliği Öğrencilerine Tavsiyeler" konulu bir sunum yaptım. 4 yıl boyunca karşılaştığım şeyleri ve nasıl yapsak daha iyi olacağından bahsettim.
Konuşma sırasında birkaç yeri atlamışım. Eksik kaldığını düşündüğüm yerleri ara verdiğimizde arkadaşlarla bir araya gelerek konuştum. Benim bahsetmediğim yerlerden Doruk Fişek benden sonraki sunumunda bahsetti. Atladığım alt başlıklar kendimizi geliştirmeyi sadece iş imkanı olarak görmemek, yapacağımız işte heyecanlı olmak, severek çalışmak ve birkaç şey daha. Heyecanlı olmak kısmını ise konuşurken uygulamalı bir şekilde gösterdim bence :) Sunumun slaytlarına buradan ulaşabilirsiniz.
Aybüke ve Gülşah birlikte çekirdeğe katkı sürecinden bahsetti. Aslında daha çok git kullanımından bahsettiler.
Muğla'da üç gün kaldık. Esra ve ailesi hepimizi evinde misafir etti. Hafta sonu Aydan, Simge ve Merve geldiler. Bol bol gezdik, eğlendik ve ilk vine videomuzu çekmiş olduk :). Aslında her şey Aybüke'nin kaza ördek demesiyle demesiyle başladı. "O ördek değil kaz" konulu videomuza buradan ulaşabilirsiniz.
Bu dönem çok sıkılmıştım benim için çok güzel bir etkinlik ve devamında tatil oldu. Esra'ya bizi evinde misafir ettiğinden, Necdet hoca ve Enis hocaya etkinliği düzenlediklerinden çok teşekkür ediyorum.
Bunlar da etkinlikten birkaç kare :)
Konuşma sırasında birkaç yeri atlamışım. Eksik kaldığını düşündüğüm yerleri ara verdiğimizde arkadaşlarla bir araya gelerek konuştum. Benim bahsetmediğim yerlerden Doruk Fişek benden sonraki sunumunda bahsetti. Atladığım alt başlıklar kendimizi geliştirmeyi sadece iş imkanı olarak görmemek, yapacağımız işte heyecanlı olmak, severek çalışmak ve birkaç şey daha. Heyecanlı olmak kısmını ise konuşurken uygulamalı bir şekilde gösterdim bence :) Sunumun slaytlarına buradan ulaşabilirsiniz.
Aybüke ve Gülşah birlikte çekirdeğe katkı sürecinden bahsetti. Aslında daha çok git kullanımından bahsettiler.
Muğla'da üç gün kaldık. Esra ve ailesi hepimizi evinde misafir etti. Hafta sonu Aydan, Simge ve Merve geldiler. Bol bol gezdik, eğlendik ve ilk vine videomuzu çekmiş olduk :). Aslında her şey Aybüke'nin kaza ördek demesiyle demesiyle başladı. "O ördek değil kaz" konulu videomuza buradan ulaşabilirsiniz.
Bu dönem çok sıkılmıştım benim için çok güzel bir etkinlik ve devamında tatil oldu. Esra'ya bizi evinde misafir ettiğinden, Necdet hoca ve Enis hocaya etkinliği düzenlediklerinden çok teşekkür ediyorum.
Bunlar da etkinlikten birkaç kare :)
Etiketler:
etkinlik,
gezegen,
mugla,
ozgur yazilim,
sunum
23 Nisan 2014 Çarşamba
Yeni Başlayanlar İçin Linux Kernel Araçları
Yorucu bir vize haftasının ardından tekrar kendimi geliştirmek için çalıştığım şeylere devam ediyorum. Aslında devam etmeye çalışıyorum çünkü gerçekten çok yorulmuşum :(. Bir de son sınıf olunca sanırım insan kendini daha çok yorulmuş hissediyor.
Linux Kernel için okuduğum şeylere devam ediyorum. Bugünlerde çekirdek geliştiricisi olmanın ne kadar güç bir şey olduğunu anlamam konusunda zirveye ulaşıyorum. Linux Kernel'a yeni başlayanlar için hazırlanan sitelerde hep bu resmin olması da bana bir işaret olabilir :)
Elbette çekirdek geliştiriciliğinin kolay bir şey olmadığının herkes gibi biliyorum. Ancak okuduğum bir yazıyı anlamak için bir kaç kere okumak, her belgenin çok uzun olması, bir çok satırda ne söylenilmek istenildiğini tam anlayamayıp on tane daha yere bakmak biraz yorucu. Bir de hatanın hangi durumlarda oluştuğunu anlayıp, o kod içerisinde oluştuğunu anlayamamak bir problem. Örneğin paylaşımlı veri yapıları ile ilgili problemleri çözebiliriz ancak o veri yapısı paylaşımlı mı nasıl anlayacağız :) gibi.
Aslında geliştiricilik olmasa bile daha güzel katkılar vermek istiyorum. Çünkü çalıştığım ilk bir ayda checkpatch.pl, sparse ve çok az coccinelle kullandım. Bunlar statik ve en temel araçlar.
checkpatch.pl ile gönderilen yamalar geliştiricilerin de okumaktan biraz sıkıldığı yamalar. Sparse ise derleme sırasında hata vermeyen ancak statik yazılım denetimi yapan ve Torvalds tarafından başlatılan bir proje.
Coccinelle ise tüm bunlardan daha farklı. Kendine özel Smpl (Semantic Patch Languange) ile yazılan anlamsal betiklerden oluşuyor. Cocci kullanırken kendimiz bir hata tipi seçiyoruz. Bu hata tipi sparse, checkpatch.pl ya da başka bir araçla alınan ya da kendi belirlediğimiz bir hata tipi olabilir. Sparse hatalarını .cocci betikleriyle düzeltmek zor. Çünkü Sparse hatalarını çözmek için tek bir standart yok ancak checkpatch.pl öyle değil. Belirlediğimiz bu hata tipi için genelde formal diller adı altında geçen statement, expression, identifier gibi kavramlarla bir şablon oluşturuyoruz. Bu hatanın çözümü için ise yine kendimiz başka bir şablon oluşturuyoruz. Aslında betikte hem hatayı hem de çözümü bir şablon halinde belirtmiş oluyoruz.
Çalıştığım bir aylık süreçte bu üç aracı öğrendim diyebilirim. Bir de smatch var ama ben kendisini hiç kullanmadım :) Bugünlerde ise modüller için dinamik test etme araçlarına bakmaya karar verdim. Hangi araçlar olduğu ve nasıl kullanıldıkları hakkında henüz bir fikrim yok :) ama standart olarak hiç fikrimin olmadığı şeylere en baştan bakıyorum. Bir de çekirdek geliştiricileri çok yoğun olduklarından çok fazla cevap atmıyorlar listelerde ya da irc'de. Bir de sanırım bu kural gibi, sana verilen bir işi listelerde sormadan kendin yapmalısın.
Geçen gün Linux Kernel katkıcısı olmak için düzenlenen Eudyptula Challenge sürecini gördüm. Aslında ortada bir challange yok :) Kendimiz basitten karmaşığa driver yazmaya başlıyoruz. Bu süreçte de her işi kendin yapmalısın ve listelerde ya da irc'de sormayın diye kesin bir şekilde belirtmişler. Bu Opw için de geçerli miydi bilmiyorum.
Önümüzdeki günlerde Muğla ve Eskişehir'de sunum yapacağım. Döndükten sonra Linux Kernel ile ilgili okuduğum şeylere devam etmeyi ve Sparse, Cocci kullanımının nasıl olduğunu burada yazmayı düşünüyorum.
Etiketler:
cocci,
coccinelle,
eudyptula challenge,
free software,
gezegen,
kernel,
linux,
opw,
smpl,
sparse
Kaydol:
Kayıtlar (Atom)