OOM問題排查,Linux進程突然被殺掉(OOM killer)


Linux 內核有個機制叫OOM killer(Out Of Memory killer),該機制會監控那些占用內存過大,尤其是瞬間占用內存很快的進程,
然后防止內存耗盡而自動把該進程殺掉。內核檢測到系統內存不足、挑選並殺掉某個進程的過程可以參考內核源代碼linux/mm/oom_kill.c,
當系統內存不足的時候,out_of_memory()被觸發,然后調用select_bad_process()選擇一個”bad”進程殺掉。
如何判斷和選擇一個”bad進程呢?linux選擇”bad”進程是通過調用oom_badness(),挑選的算法和想法都很簡單很朴實:
最bad的那個進程就是那個最占用內存的進程。 具體OOM的解釋可以看這篇文章:http:
//www.wowotech.net/memory_management/oom.html

 1.預備知識

在解讀日志之前,我們先回顧一下linux內核的內存管理。

(1)Page 頁

處理器的最小‘尋址單元’是字節或者字,而頁是內存的‘管理單元’。

(2) Zone 區

(a)區存在的原因:

有些硬件設備只能對特定的內存地址執行DMA(direct memory access)操作。

在一些架構中,實際物理內存是比系統可尋址的虛擬內存要大的,這就導致有些物理內存沒有辦法被永久的映射在內核的地址空間中。

區的划分也是直接以上面兩個原因為依據的。

(b)區的種類 

ZONE_DMA—這個區包含的page可以執行DMA操作。這部分區域的大小和CPU架構有關,在x86架構中,該部分區域大小限制為16MB。

ZONE_DMA32—類似於ZOME_DMA, 這個區也包含可以執行DMA操作的page。該區域只存在於64位系統中,適合32位的設備訪問。

ZONE_NORMAL—這個區包含可以正常映射到地址空間中的page,或者說這個區包含了除了DMA和HIGHMEM以外的內存。許多內核操作都僅在這個區域進行。

ZONE_HIGHMEM—這個區包含的是high memory,也就是那些不能被永久映射到內核地址空間的頁。

32位的x86架構中存在三種內存區域,ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM。根據地址空間划分的不同,三個區域的大小不一樣:

1)1G內核空間/3G用戶空間

2) 4G內核空間/4G用戶空間

64位的系統由於尋址能力的提高,不存在highmem區,所以64位系統中存在的區有DMA,DMA32和NORMAL三個區。




1.2 內核分配內存的函數

下面是內核分配內存的核心函數之一,它會分配2的order次方個連續的物理頁內存,並將第一頁的邏輯地址返回。

unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)

內核空間的內存分配函數和用戶空間最大的不同就是每個函數會有一個gfp_mask參數。

其中gfp 代表的就是我們上面的內存分配函數 __get_free_pages()。

gfp_mask可以分成三種: 行為修飾符(action modifier),區修飾符 (zone modifier)和類型( type).

(1)行為修飾符是用來指定內核該如何分配內存的。比如分配內存時是否可以進行磁盤io,是否可以進行文件系統操作,內核是否可以睡眠(sleep)等等。

(2)區修飾符指定內存需要從哪個區來分配。

(3)類型是行為修飾符和區修飾符結合之后的產物。在一些特定的內存分配場合下,我們可能需要同時指定多個行為修飾符和區修飾符,而type就是針對這些固定的場合,將所需要的行為修飾符和區修飾符都整合到了一起,這樣使用者只要指定一個type就可以了。

不同type所代表的含義可以參看下面的表格:



2 日志解讀

 下面是從oom killer被觸發到進程到被殺掉的一個大概過程,我們來具體看一下。

Mar 25 03:02:44 BJPVZXJL-1 kernel: easy_collector invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0
Mar 25 03:02:44 BJPVZXJL-1 kernel: easy_collector cpuset=/ mems_allowed=0
Mar 25 03:02:44 BJPVZXJL-1 kernel: CPU: 4 PID: 4575 Comm: easy_collector Tainted: G OE ------------ 3.10.0-957.12.2.el7.x86_64 #1
Mar 25 03:02:44 BJPVZXJL-1 kernel: Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS 8a46cfe 04/01/2014
Mar 25 03:02:44 BJPVZXJL-1 kernel: Call Trace:
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb63041>] dump_stack+0x19/0x1b
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb5da6a>] dump_header+0x90/0x229
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c501212>] ? ktime_get_ts64+0x52/0xf0
Mar 25 03:00:01 BJPVZXJL-1 systemd: Started Session 772087 of user root.
Mar 25 03:00:01 BJPVZXJL-1 systemd: Started Session 772088 of user root.
Mar 25 03:00:01 BJPVZXJL-1 systemd: Started Session 772089 of user root.
Mar 25 03:00:01 BJPVZXJL-1 systemd: Started Session 772090 of user root.
Mar 25 03:01:01 BJPVZXJL-1 systemd: Started Session 772092 of user root.
Mar 25 03:01:01 BJPVZXJL-1 systemd: Started Session 772091 of user root.
Mar 25 03:02:01 BJPVZXJL-1 systemd: Started Session 772093 of user root.
Mar 25 03:02:01 BJPVZXJL-1 systemd: Started Session 772095 of user root.
Mar 25 03:02:01 BJPVZXJL-1 systemd: Started Session 772094 of user root.
Mar 25 03:02:44 BJPVZXJL-1 kernel: easy_collector invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0
Mar 25 03:02:44 BJPVZXJL-1 kernel: easy_collector cpuset=/ mems_allowed=0
Mar 25 03:02:44 BJPVZXJL-1 kernel: CPU: 4 PID: 4575 Comm: easy_collector Tainted: G OE ------------ 3.10.0-957.12.2.el7.x86_64 #1
Mar 25 03:02:44 BJPVZXJL-1 kernel: Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS 8a46cfe 04/01/2014
Mar 25 03:02:44 BJPVZXJL-1 kernel: Call Trace:
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb63041>] dump_stack+0x19/0x1b
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb5da6a>] dump_header+0x90/0x229
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c501212>] ? ktime_get_ts64+0x52/0xf0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c55845f>] ? delayacct_end+0x8f/0xb0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5ba7b4>] oom_kill_process+0x254/0x3d0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5ba25d>] ? oom_unkillable_task+0xcd/0x120
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5ba306>] ? find_lock_task_mm+0x56/0xc0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5baff6>] out_of_memory+0x4b6/0x4f0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb5e56e>] __alloc_pages_slowpath+0x5d6/0x724
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5c13d4>] __alloc_pages_nodemask+0x404/0x420
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c60e288>] alloc_pages_current+0x98/0x110
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5b6617>] __page_cache_alloc+0x97/0xb0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5b9278>] filemap_fault+0x298/0x490
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffffc0494186>] ext4_filemap_fault+0x36/0x50 [ext4]
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5e476a>] __do_fault.isra.59+0x8a/0x100
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5e4d1c>] do_read_fault.isra.61+0x4c/0x1b0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5e96c4>] handle_pte_fault+0x2f4/0xd10
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c65843d>] ? core_sys_select+0x26d/0x340
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9c5ec1fd>] handle_mm_fault+0x39d/0x9b0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb70603>] __do_page_fault+0x203/0x4f0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb709d6>] trace_do_page_fault+0x56/0x150
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb6ff62>] do_async_page_fault+0x22/0xf0
Mar 25 03:02:44 BJPVZXJL-1 kernel: [<ffffffff9cb6c798>] async_page_fault+0x28/0x30
Mar 25 03:02:44 BJPVZXJL-1 kernel: Mem-Info:
Mar 25 03:02:44 BJPVZXJL-1 kernel: active_anon:1872940 inactive_anon:85 isolated_anon:0#012 active_file:5818 inactive_file:7456 isolated_file:32#012 unevictable:0 dirty:3
writeback:0 unstable:0#012 slab_reclaimable:10679 slab_unreclaimable:8296#012 mapped:487 shmem:196 pagetables:6158 bounce:0#012 free:25631 free_pcp:1598 free_cma:0
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 DMA free:15908kB min:132kB low:164kB high:196kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0
kB isolated(anon):0kB isolated(file):0kB present:15992kB managed:15908kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:0
kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
Mar 25 03:02:44 BJPVZXJL-1 kernel: lowmem_reserve[]: 0 2812 7802 7802
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 DMA32 free:43660kB min:24312kB low:30388kB high:36468kB active_anon:2716820kB inactive_anon:92kB active_file:4228kB inactive_file
:7100kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:3129192kB managed:2882968kB mlocked:0kB dirty:12kB writeback:0kB mapped:560kB shmem:212kB slab_reclai
mable:13480kB slab_unreclaimable:10992kB kernel_stack:3744kB pagetables:8256kB unstable:0kB bounce:0kB free_pcp:3508kB local_pcp:280kB free_cma:0kB writeback_tmp:0kB pages
_scanned:24664 all_unreclaimable? yes
Mar 25 03:02:44 BJPVZXJL-1 kernel: lowmem_reserve[]: 0 0 4989 4989
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 Normal free:42956kB min:43132kB low:53912kB high:64696kB active_anon:4774940kB inactive_anon:248kB active_file:19044kB inactive_f
ile:22724kB unevictable:0kB isolated(anon):0kB isolated(file):128kB present:5242880kB managed:5109360kB mlocked:0kB dirty:0kB writeback:0kB mapped:1388kB shmem:572kB slab_
reclaimable:29236kB slab_unreclaimable:22192kB kernel_stack:8592kB pagetables:16376kB unstable:0kB bounce:0kB free_pcp:2884kB local_pcp:124kB free_cma:0kB writeback_tmp:0k
B pages_scanned:54356 all_unreclaimable? yes
Mar 25 03:02:44 BJPVZXJL-1 kernel: lowmem_reserve[]: 0 0 0 0
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 DMA: 1*4kB (U) 0*8kB 0*16kB 1*32kB (U) 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15908k
B
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 DMA32: 425*4kB (UEM) 172*8kB (UEM) 134*16kB (UEM) 132*32kB (UEM) 233*64kB (UEM) 128*128kB (UEM) 12*256kB (UEM) 0*512kB 0*1024kB 0
*2048kB 0*4096kB = 43812kB
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 Normal: 729*4kB (UE) 798*8kB (UE) 744*16kB (UE) 555*32kB (UEM) 34*64kB (UEM) 11*128kB (UE) 3*256kB (UE) 0*512kB 0*1024kB 0*2048kB
0*4096kB = 43316kB
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
Mar 25 03:02:44 BJPVZXJL-1 kernel: 14026 total pagecache pages
Mar 25 03:02:44 BJPVZXJL-1 kernel: 0 pages in swap cache
Mar 25 03:02:44 BJPVZXJL-1 kernel: Swap cache stats: add 0, delete 0, find 0/0
Mar 25 03:02:44 BJPVZXJL-1 kernel: Free swap = 0kB
Mar 25 03:02:44 BJPVZXJL-1 kernel: Total swap = 0kB
Mar 25 03:02:44 BJPVZXJL-1 kernel: 2097016 pages RAM
Mar 25 03:02:44 BJPVZXJL-1 kernel: 0 pages HighMem/MovableOnly
Mar 25 03:02:44 BJPVZXJL-1 kernel: 94957 pages reserved
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 1654] 0 1654 16203 117 35 0 0 systemd-journal
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 1678] 0 1678 11204 226 24 0 -1000 systemd-udevd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 1683] 0 1683 47590 99 29 0 0 lvmetad
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3149] 0 3149 13880 112 27 0 -1000 auditd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3182] 0 3182 75446 2218 28 0 0 CmsGoAgent.linu
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3183] 999 3183 153164 2254 62 0 0 polkitd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3186] 0 3186 5416 82 15 0 0 irqbalance
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3197] 81 3197 14556 164 32 0 -900 dbus-daemon
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3204] 38 3204 11818 178 29 0 0 ntpd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3224] 0 3224 6702 186 19 0 0 systemd-logind
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3238] 32 3238 17332 168 38 0 0 rpcbind
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3268] 0 3268 48775 118 35 0 0 gssproxy
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3282] 0 3282 31579 174 18 0 0 crond
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3287] 0 3287 6476 53 18 0 0 atd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3300] 0 3300 27523 34 10 0 0 agetty
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3301] 0 3301 27523 34 10 0 0 agetty
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3311] 0 3311 540824 6666 95 0 0 exe
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3512] 0 3512 25710 519 47 0 0 dhclient
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3579] 0 3579 347531 6501 438 0 0 rsyslogd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3582] 0 3582 143483 2788 95 0 0 tuned
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 3981] 0 3981 28216 260 57 0 -1000 sshd
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 4503] 0 4503 231103 3007 50 0 0 easyAgent
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 4575] 0 4575 93554 3203 65 0 0 easy_collector
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 4576] 0 4576 118079 3938 83 0 0 easy_collector
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 4577] 0 4577 158580 6926 92 0 0 easy_collector
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 4586] 0 4586 95280 3394 73 0 0 easy_monitor
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 5465] 0 5465 109224 147 28 0 0 AliSecGuard
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 6502] 0 6502 370821 20447 114 0 0 n9e-collector
Mar 25 03:02:44 BJPVZXJL-1 kernel: [25907] 0 25907 8133 358 20 0 0 AliYunDunUpdate
Mar 25 03:02:44 BJPVZXJL-1 kernel: [26058] 0 26058 39401 6788 76 0 0 AliYunDun
Mar 25 03:02:44 BJPVZXJL-1 kernel: [23520] 1003 23520 1822301 470784 1181 0 0 java
Mar 25 03:02:44 BJPVZXJL-1 kernel: [21969] 1003 21969 2107100 542660 1304 0 0 java
Mar 25 03:02:44 BJPVZXJL-1 kernel: [17330] 0 17330 111143 11199 96 0 0 titanagent
Mar 25 03:02:44 BJPVZXJL-1 kernel: [25907] 0 25907 8133 358 20 0 0 AliYunDunUpdate
Mar 25 03:02:44 BJPVZXJL-1 kernel: [26058] 0 26058 39401 6788 76 0 0 AliYunDun
Mar 25 03:02:44 BJPVZXJL-1 kernel: [23520] 1003 23520 1822301 470784 1181 0 0 java
Mar 25 03:02:44 BJPVZXJL-1 kernel: [21969] 1003 21969 2107100 542660 1304 0 0 java
Mar 25 03:02:44 BJPVZXJL-1 kernel: [17330] 0 17330 111143 11199 96 0 0 titanagent
Mar 25 03:02:44 BJPVZXJL-1 kernel: [17332] 0 17332 21926 104 13 0 0 titan_monitor
Mar 25 03:02:44 BJPVZXJL-1 kernel: [25236] 0 25236 201609 1405 14 0 0 aliyun-service
Mar 25 03:02:44 BJPVZXJL-1 kernel: [25359] 0 25359 4450 122 12 0 0 assist_daemon
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 658] 1003 658 2118259 771363 1734 0 0 java
Mar 25 03:02:44 BJPVZXJL-1 kernel: [ 1322] 0 1322 30815 63 16 0 0 anacron
Mar 25 03:02:44 BJPVZXJL-1 kernel: Out of memory: Kill process 658 (java) score 386 or sacrifice child
Mar 25 03:02:44 BJPVZXJL-1 kernel: Killed process 658 (java) total-vm:8473036kB, anon-rss:3085452kB, file-rss:0kB, shmem-rss:0kB

 
          
 

先來看一下第一行,它給出了oom killer是由誰觸發的信息。

nginx invoked oom-killer: gfp_mask=0x200da, order=0, oom_score_adj=0

order=0 告訴我們所請求的內存的大小是多少,即nginx請求了2的0次方這么多個page的內存,也就是一個page,或者說是4KB。

gfp_mask的最后兩個bit代表的是zone mask,也就是說它指明內存應該從哪個區來分配。

Flag value Description

 
 

__GFP_DMA 0x01u Allocate from ZONE_DMA if possible

__GFP_HIGHMEM 0x02u Allocate from ZONE_HIGHMEM if possible

(這里有一點需要注意,在64位的x86系統中,是沒有highmem區的,64位系統中的normal區就對應上表中的highmem區。)

在本案例中,zonemask是2,也就是說nginx正在從zone-normal(64位系統)中請求內存。

其他標志位的含義如下:


所以我們當前這個內存請求帶有這幾個標志:GFP_NORECLAIM,GFP_FS,GFP_IO,GFP_WAIT, 都是比較正常的幾個標志,那么我們這個請求為什么會有問題呢?繼續往下看,可以看到下面的信息:

Mar 25 03:02:44 BJPVZXJL-1 kernel: Node 0 Normal free:42956kB min:43132kB low:53912kB high:64696kB active_anon:4774940kB inactive_anon:248kB active_file:19044kB inactive_f
ile:22724kB unevictable:0kB isolated(anon):0kB isolated(file):128kB present:5242880kB managed:5109360kB mlocked:0kB dirty:0kB writeback:0kB mapped:1388kB shmem:572kB slab_
reclaimable:29236kB slab_unreclaimable:22192kB kernel_stack:8592kB pagetables:16376kB unstable:0kB bounce:0kB free_pcp:2884kB local_pcp:124kB free_cma:0kB writeback_tmp:0k
B pages_scanned:54356 all_unreclaimable? yes

可以看到normal區free的內存只有42956kB,比系統允許的最小值(min)43132kB還要低,這意味着application已經無法再從系統中申請到內存了,並且系統會開始啟動oom killer來緩解系統內存壓力。

這里我們說一下一個常見的誤區,就是有人會認為觸發了oom-killer的進程就是問題的罪魁禍首,比如我們這個例子中的這個nginx進程。其實日志中invoke oom-killer的這個進程有時候可能只是一個受害者,因為其他應用/進程已將系統內存用盡,而這個invoke oomkiller的進程恰好在此時發起了一個分配內存的請求而已。在系統內存已經不足的情況下,任何一個內存請求都可能觸發oom killer的啟動。

oom-killer的啟動會使系統從用戶空間轉換到內核空間。內核會在短時間內進行大量的工作,比如計算每個進程的oom分值,從而篩選出最適合殺掉的進程。我們從日志中也可以看到這一篩選過程

 pid:進程ID uid:用戶ID tgid:線程組ID total_vm:虛擬內存使用(單位為4 kB內存頁) rss: Resident Set Size(常駐內存集)單位是內存頁數,同樣的每頁4 KB nr_ptes:頁表項 swapents:交換條目 oom_score_adj 通常為0;較低的數字表示當調用OOM殺手時,進程將不太可能死亡。

 

因此如果還需要內存的話則超過了系統的內存,導致了內存溢出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM