ฉันสนใจที่จะแก้ไขเคอร์เนลภายในใช้แพตช์จัดการไดรเวอร์อุปกรณ์และโมดูลเพื่อความสนุกส่วนตัวของฉันเอง
มีทรัพยากรที่ครอบคลุมสำหรับการแฮ็กเคอร์เนลสำหรับโปรแกรมเมอร์ที่มีประสบการณ์หรือไม่?
ฉันสนใจที่จะแก้ไขเคอร์เนลภายในใช้แพตช์จัดการไดรเวอร์อุปกรณ์และโมดูลเพื่อความสนุกส่วนตัวของฉันเอง
มีทรัพยากรที่ครอบคลุมสำหรับการแฮ็กเคอร์เนลสำหรับโปรแกรมเมอร์ที่มีประสบการณ์หรือไม่?
คำตอบ:
**TODO** +editPic: Linux Kernel Developer -> (Ring Layer 0)
+addSection: Kernel Virtualization Engine
KERN_WARN_CODING_STYLE: Do not Loop unless you absolutely have to.
แนะนำหนังสือสำหรับเตรียม
void *i
"ผู้ชายไม่เข้าใจหนังสือจนกว่าพวกเขาจะมีจำนวนหนึ่งในชีวิตหรือไม่ว่าในกรณีใดก็ตามไม่มีใครเข้าใจหนังสือที่ลึกจนกว่าเขาจะได้เห็นและใช้ชีวิตอย่างน้อยส่วนหนึ่งของเนื้อหา" –Ezra Pound
การเดินทางหนึ่งพันไมล์รหัสต้องเริ่มต้นด้วยขั้นตอนเดียว หากคุณสับสนว่าหนังสือต่อไปนี้เล่มใดที่เริ่มต้นด้วยไม่ต้องกังวลเลือกตัวเลือกใดตัวเลือกหนึ่งของคุณ ไม่ใช่ทุกคนที่หลงทาง ขณะที่ถนนทุกสายในที่สุดเชื่อมต่อกับทางหลวงคุณจะสำรวจสิ่งใหม่ ๆ ในการเดินทางเคอร์เนลของคุณเป็นหน้าความคืบหน้าโดยไม่ต้องประชุมปลายตายใด ๆ code-set
และในที่สุดเชื่อมต่อกับ อ่านด้วยใจแจ้งเตือนและจำไว้ว่ารหัสไม่ได้เป็นวรรณกรรม
สิ่งที่เหลืออยู่ไม่ใช่สิ่งหรืออารมณ์หรือภาพหรือภาพจิตหรือหน่วยความจำหรือแม้แต่ความคิด มันเป็นฟังก์ชั่น กระบวนการของการเรียงลำดับบางอย่าง แง่มุมของชีวิตที่สามารถอธิบายได้ว่าเป็นหน้าที่ของบางสิ่งที่ "ใหญ่กว่า" และดังนั้นจึงปรากฏว่าไม่ใช่ "แยก" ออกจากสิ่งอื่น เช่นเดียวกับฟังก์ชั่นของมีด - บางสิ่งบางอย่าง - ไม่ได้แยกออกจากมีดเอง ฟังก์ชั่นอาจใช้งานหรือไม่ได้ใช้งานในขณะนี้ แต่อาจไม่เคยแยกจากกัน
Solovay Strassen Derandomized Algorithm สำหรับการทดสอบเบื้องต้น :
อ่านไม่ให้ขัดแย้งและสับสน ไม่เชื่อและรับอนุญาต; ไม่หาพูดคุยและสนทนา แต่ต้องชั่งน้ำหนักและพิจารณา หนังสือบางเล่มจะต้องถูกลิ้มรสคนอื่น ๆ จะถูกกลืนและบางคนก็ต้องเคี้ยวและย่อย: นั่นคือหนังสือบางเล่มจะต้องอ่านเฉพาะในส่วนอื่น ๆ ที่จะอ่าน แต่ไม่อยากรู้อยากเห็นและไม่กี่คนที่จะอ่านทั้งหมด และด้วยความขยันและความสนใจ
static void tasklet_hi_action(struct softirq_action *a)
{
struct tasklet_struct *list;
local_irq_disable();
list = __this_cpu_read(tasklet_hi_vec.head);
__this_cpu_write(tasklet_hi_vec.head, NULL);
__this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head));
local_irq_enable();
while (list) {
struct tasklet_struct *t = list;
list = list->next;
if (tasklet_trylock(t)) {
if (!atomic_read(&t->count)) {
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
&t->state))
BUG();
t->func(t->data);
tasklet_unlock(t);
continue;
}
tasklet_unlock(t);
}
local_irq_disable();
t->next = NULL;
*__this_cpu_read(tasklet_hi_vec.tail) = t;
__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
__raise_softirq_irqoff(HI_SOFTIRQ);
local_irq_enable();
}
}
Core Linux (5 -> 1 -> 3 -> 2 -> 7 -> 4 -> 6)
“ ธรรมชาติไม่มีเคอร์เนลและเปลือกหอย เธอคือทุกอย่างในทันที "- โยฮันน์โวล์ฟกังฟอนเกอเธ่
ผู้อ่านควรจะรอบรู้กับแนวคิดระบบปฏิบัติการ ; ความเข้าใจที่เป็นธรรมของกระบวนการที่ใช้เวลานานและความแตกต่างกับกระบวนการที่มีการประมวลผลระยะสั้น การยอมรับข้อบกพร่องในขณะที่ตอบสนองต่อข้อ จำกัด แบบเรียลไทม์และนุ่ม ในขณะที่อ่านสิ่งสำคัญคือการเข้าใจและn/ack
ตัวเลือกการออกแบบที่ทำโดยเคอร์เนล linux ในระบบย่อยหลัก
สัญญาณ [และ] สัญญาณ [เป็น] เส้นทางที่ขึ้นอยู่กับความทุกข์ยากความสิ้นหวังความสยองขวัญและความบ้าคลั่ง (~ Anthony Baxte) ที่ถูกกล่าวว่าคุณควรจะเป็นผู้เชี่ยวชาญการประเมินตนเอง C ก่อนที่จะดำน้ำในเคอร์เนล คุณควรมีประสบการณ์ที่ดีกับรายการที่เชื่อมโยงสแต็กคิวต้นไม้แดงดำฟังก์ชันแฮชและอื่น ๆ
volatile int i;
int main(void)
{
int c;
for (i=0; i<3; i++) {
c = i&&&i;
printf("%d\n", c); /* find c */
}
return 0;
}
ความงามและศิลปะของซอร์ส Linux Kernel นั้นอยู่ในการใช้รหัสที่ทำให้สับสนโดยเจตนา นี่มักจะเป็นสิ่งที่จำเป็นในการถ่ายทอดความหมายของการคำนวณที่เกี่ยวข้องกับการดำเนินการสองอย่างหรือมากกว่าในวิธีที่สะอาดและสง่างาม โดยเฉพาะอย่างยิ่งเมื่อเขียนโค้ดสำหรับสถาปัตยกรรมแบบมัลติคอร์
วิดีโอการบรรยายเกี่ยวกับระบบ Real-Time ,เวลางาน ,การบีบอัดหน่วยความจำ ,ปัญหาและอุปสรรคที่หน่วยความจำ , SMP
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
ไดรเวอร์อุปกรณ์ Linux (1 -> 2 -> 4 -> 3 -> 8 -> ... )
"ดนตรีไม่ได้ติดตัวคุณต้องพกมันไปด้วยความสามารถของคุณที่จะมุ่งเน้นไปที่อารมณ์หรือเรื่องราวเล็ก ๆ น้อย ๆ " - เด็บบี้แฮร์รี่
งานของคุณนั้นโดยทั่วไปแล้วจะสร้างอินเทอร์เฟซการสื่อสารความเร็วสูงระหว่างอุปกรณ์ฮาร์ดแวร์และเคอร์เนลซอฟต์แวร์ คุณควรอ่านแผ่นข้อมูล / คู่มืออ้างอิงฮาร์ดแวร์เพื่อทำความเข้าใจพฤติกรรมของอุปกรณ์และการควบคุมและสถานะข้อมูลและช่องทางกายภาพที่ให้ไว้ ความรู้เกี่ยวกับการประกอบสำหรับสถาปัตยกรรมเฉพาะของคุณและความรู้พื้นฐานของ VLSI ฮาร์ดแวร์คำอธิบายภาษาเช่น VHDL หรือ Verilog จะช่วยคุณในระยะยาว
ถาม : แต่ทำไมฉันต้องอ่านรายละเอียดฮาร์ดแวร์?
ตอบ : เนื่องจาก "มีคาร์บอนและซิลิกอนที่ซอฟต์แวร์ไม่สามารถเชื่อมต่อได้" - ราหุลสนาด
แต่ข้างบนไม่ได้โพสท่าเป็นปัญหาสำหรับการคำนวณอัลกอริทึม ( รหัสไดร์เวอร์ - ล่างครึ่งประมวลผล ) ขณะที่มันสามารถจำลองได้อย่างเต็มที่บนเครื่องนิเวอร์แซลทัวริง หากผลการคำนวณถือเป็นจริงในโดเมนทางคณิตศาสตร์ก็แน่นอนว่ามันยังเป็นความจริงในขอบเขตทางกายภาพ
วิดีโอการบรรยายเกี่ยวกับไดรเวอร์อุปกรณ์ Linux (Lec. 17 & 18),กายวิภาคของไดรเวอร์ KMS ในตัว ,การควบคุมพินและการอัพเดต GPIO ,กรอบนาฬิกาทั่วไป ,เขียนไดรเวอร์ Linux จริง - Greg KH
static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;
if (PHY_HALTED == phydev->state)
return IRQ_NONE; /* It can't be ours. */
/* The MDIO bus is not allowed to be written in interrupt
* context, so we need to disable the irq here. A work
* queue will write the PHY to disable and clear the
* interrupt, and then reenable the irq line.
*/
disable_irq_nosync(irq);
atomic_inc(&phydev->irq_disable);
queue_work(system_power_efficient_wq, &phydev->phy_queue);
return IRQ_HANDLED;
}
เครือข่ายเคอร์เนล (1 -> 2 -> 3 -> ... )
“ เรียกมันว่าเผ่าเรียกมันว่าเครือข่ายหรือเรียกว่าชนเผ่าเรียกมันว่าครอบครัว: ไม่ว่าคุณจะเรียกมันว่าอะไรก็ตามไม่ว่าคุณจะเป็นใครก็ตามคุณต้องการมัน” - Jane Howard
การทำความเข้าใจแพ็กเก็ตแบบ walk-through ในเคอร์เนลเป็นกุญแจสำคัญในการทำความเข้าใจกับการเชื่อมต่อเครือข่ายเคอร์เนล การทำความเข้าใจมันเป็นสิ่งที่จำเป็นถ้าเราต้องการที่จะเข้าใจ Netfilter หรือ IPSec ภายในและอื่น ๆ โครงสร้างที่สำคัญที่สุดสองประการของเลเยอร์เครือข่ายเคอร์เนลของ linux คือ: struct sk_buff
และstruct net_device
static inline int sk_hashed(const struct sock *sk)
{
return !sk_unhashed(sk);
}
การดีบักเคอร์เนล (1 -> 4 -> 9 -> ... )
เว้นแต่จะมีการสื่อสารกับสิ่งใดสิ่งหนึ่งบอกว่าสิ่งใดหมายถึงปัญหาจะผูกพันกับผล ~ Alan Turing เกี่ยวกับคอมพิวเตอร์
Brian W. Kernighan ใน Unix สำหรับผู้เริ่มต้น (1979) กล่าวว่า "เครื่องมือดีบั๊กที่มีประสิทธิภาพมากที่สุดยังคงคิดอย่างระมัดระวังควบคู่ไปกับคำสั่งการพิมพ์ที่รอบคอบ" การรู้ว่าจะเก็บรวบรวมอะไรจะช่วยให้คุณได้รับข้อมูลที่ถูกต้องอย่างรวดเร็วเพื่อการวินิจฉัยที่รวดเร็ว นักวิทยาศาสตร์คอมพิวเตอร์ผู้ยิ่งใหญ่ Edsger Dijkstra เคยกล่าวไว้ว่าการทดสอบสามารถแสดงให้เห็นถึงการมีอยู่ของข้อบกพร่อง แต่ไม่ใช่การหายไป วิธีปฏิบัติในการสืบสวนที่ดีควรสร้างสมดุลระหว่างความต้องการในการแก้ปัญหาอย่างรวดเร็วความจำเป็นในการสร้างทักษะของคุณและการใช้ผู้เชี่ยวชาญอย่างมีประสิทธิภาพ
มีหลายครั้งที่คุณกดจุดต่ำสุดดูเหมือนว่าไม่มีอะไรทำงานได้และคุณหมดทางเลือกทั้งหมด จากนั้นการดีบักจริงจะเริ่มขึ้น ข้อผิดพลาดอาจให้การหยุดพักที่คุณต้องปลดจากการแก้ไขปัญหาที่ไม่มีประสิทธิภาพ
วิดีโอการบรรยายเกี่ยวกับการดีบักเคอร์เนลและการทำโปรไฟล์ , การวิเคราะห์การถ่ายโอนข้อมูลหลัก ,การดีบักมัลติคอร์ด้วย GDB , การควบคุมสภาวะการแข่งขันแบบมัลติคอร์ ,การดีบักอุปกรณ์อิเล็กทรอนิกส์
/* Buggy Code -- Stack frame problem
* If you require information, do not free memory containing the information
*/
char *initialize() {
char string[80];
char* ptr = string;
return ptr;
}
int main() {
char *myval = initialize();
do_something_with(myval);
}
/* “When debugging, novices insert corrective code; experts remove defective code.”
* – Richard Pattis
#if DEBUG
printk("The above can be considered as Development and Review in Industrial Practises");
#endif
*/
ระบบไฟล์ (1 -> 2 -> 6 -> ... )
"ฉันต้องการมีหน่วยความจำเสมือนอย่างน้อยที่สุดมันก็เป็นระบบคู่กับระบบไฟล์" - เคนทอมป์สัน
บนระบบ UNIX ทุกอย่างเป็นไฟล์ หากบางสิ่งไม่ใช่ไฟล์มันเป็นกระบวนการยกเว้นไพพ์ที่มีชื่อและซ็อกเก็ต ในระบบไฟล์ไฟล์จะถูกแทนด้วยinode
หมายเลขซีเรียลประเภทที่มีข้อมูลเกี่ยวกับข้อมูลจริงที่ประกอบเป็นไฟล์ Linux Virtual File System VFS
แคชข้อมูลในหน่วยความจำจากแต่ละระบบไฟล์ขณะที่ถูกเมาท์และใช้งาน ต้องใช้ความระมัดระวังอย่างมากในการอัปเดตระบบไฟล์อย่างถูกต้องเนื่องจากข้อมูลภายในแคชเหล่านี้ได้รับการแก้ไขเมื่อไฟล์และไดเรกทอรีถูกสร้างเขียนและลบ สิ่งสำคัญที่สุดของแคชเหล่านี้คือ Buffer Cache ซึ่งถูกรวมเข้ากับวิธีที่แต่ละระบบไฟล์เข้าถึงอุปกรณ์เก็บข้อมูลบล็อกพื้นฐาน
วิดีโอการบรรยายเกี่ยวกับระบบการจัดเก็บ ,แฟลชมิตรระบบไฟล์
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
struct open_flags op;
int fd = build_open_flags(flags, mode, &op);
struct filename *tmp;
if (fd)
return fd;
tmp = getname(filename);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
fd = get_unused_fd_flags(flags);
if (fd >= 0) {
struct file *f = do_filp_open(dfd, tmp, &op);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fsnotify_open(f);
fd_install(fd, f);
}
}
putname(tmp);
return fd;
}
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, filename, flags, mode);
}
ความปลอดภัย (1 -> 2 -> 8 -> 4 -> 3 -> ... )
"UNIX ไม่ได้ถูกออกแบบมาเพื่อหยุดผู้ใช้จากการทำสิ่งที่โง่เขลาเช่นเดียวกับที่จะหยุดพวกเขาจากการทำสิ่งที่ฉลาด" - ดั๊กกวิน
ไม่มีเทคนิคทำงานหากไม่ได้ใช้ จริยธรรมเปลี่ยนไปด้วยเทคโนโลยี
" F × S = k " ผลิตภัณฑ์ที่มีเสรีภาพและความปลอดภัยเป็นค่าคงที่ - กฎของนิเวน
การเข้ารหัสเป็นพื้นฐานของความไว้วางใจออนไลน์ การแฮ็กใช้ประโยชน์จากการควบคุมความปลอดภัยไม่ว่าจะเป็นทางด้านเทคนิคทางกายภาพหรือองค์ประกอบมนุษย์ การปกป้องเคอร์เนลจากโปรแกรมที่รันอยู่เป็นขั้นตอนแรกสู่ระบบที่ปลอดภัยและมั่นคง แต่เห็นได้ชัดว่าไม่เพียงพอ: ระดับการป้องกันบางอย่างจะต้องมีอยู่ระหว่างแอปพลิเคชันผู้ใช้ที่แตกต่างกัน การหาประโยชน์สามารถกำหนดเป้าหมายไปยังบริการท้องถิ่นหรือระยะไกล
“ คุณไม่สามารถแฮกชะตาของคุณกำลังดุร้าย ... คุณต้องมีประตูหลังช่องด้านข้างเข้ามาในชีวิต” - Clyde Dsouza
คอมพิวเตอร์ไม่ได้แก้ปัญหาพวกเขาดำเนินการแก้ปัญหา เบื้องหลังโค้ดอัลกอริทึมที่ไม่สามารถกำหนดค่าได้ทุกอย่างจะมีจิตใจที่ ตั้งใจแน่วแน่ - / var / log / dmesg
วิดีโอการบรรยายเกี่ยวกับการเข้ารหัสและการรักษาความปลอดภัยเครือข่าย , Namespaces เพื่อความปลอดภัย ,การป้องกันการโจมตีระยะไกล ,ลินุกซ์ฝังตัวที่ปลอดภัย
env x='() { :;}; echo vulnerable' bash -c "echo this is a test for Shellsock"
Kernel Source (0.11 -> 2.4 -> 2.6 -> 3.18)
"เช่นเดียวกับไวน์ความเชี่ยวชาญของการเขียนโปรแกรมเคอร์เนลจะเติบโตขึ้นตามกาลเวลา แต่ไม่เหมือนกับไวน์ - ลอเรนซ์ Mucheka
คุณอาจไม่คิดว่าโปรแกรมเมอร์เป็นศิลปิน แต่การเขียนโปรแกรมเป็นอาชีพที่สร้างสรรค์อย่างยิ่ง มันเป็นความคิดสร้างสรรค์ที่อิงตรรกะ การศึกษาด้านวิทยาการคอมพิวเตอร์ไม่สามารถทำให้ใครเป็นโปรแกรมเมอร์ผู้เชี่ยวชาญได้มากกว่าการศึกษาพู่กันและรงควัตถุสามารถทำให้ใครคนหนึ่งเป็นจิตรกรผู้เชี่ยวชาญ ดังที่คุณทราบแล้วมีความแตกต่างระหว่างการรู้เส้นทางและเส้นทางนั้น มันมีความสำคัญที่สุดในการพับแขนเสื้อและทำให้มือสกปรกด้วยซอร์สโค้ดเคอร์เนล สุดท้ายกับเคอร์เนลของคุณได้รับจึงมีความรู้ทุกที่ที่คุณไปคุณจะส่องแสง
coders อ่อนเลียนแบบ; ขโมยรหัสผู้ใหญ่ขโมย; coders ที่ไม่ดีจะกำหนดสิ่งที่พวกเขาใช้และตัวเข้ารหัสที่ดีทำให้มันเป็นสิ่งที่ดีกว่าหรืออย่างน้อยก็เป็นสิ่งที่แตกต่างกัน ผู้เข้ารหัสที่ดีเชื่อมโยงการขโมยของเขาเข้ากับความรู้สึกทั้งหมดซึ่งเป็นเอกลักษณ์แตกต่างจากที่เคยฉีกขาดอย่างสิ้นเชิง
วิดีโอการบรรยายเกี่ยวกับสูตรเคอร์เนล
linux-0.11
├── boot
│ ├── bootsect.s head.s setup.s
├── fs
│ ├── bitmap.c block_dev.c buffer.c char_dev.c exec.c
│ ├── fcntl.c file_dev.c file_table.c inode.c ioctl.c
│ ├── namei.c open.c pipe.c read_write.c
│ ├── stat.c super.c truncate.c
├── include
│ ├── a.out.h const.h ctype.h errno.h fcntl.h
│ ├── signal.h stdarg.h stddef.h string.h termios.h
│ ├── time.h unistd.h utime.h
│ ├── asm
│ │ ├── io.h memory.h segment.h system.h
│ ├── linux
│ │ ├── config.h fdreg.h fs.h hdreg.h head.h
│ │ ├── kernel.h mm.h sched.h sys.h tty.h
│ ├── sys
│ │ ├── stat.h times.h types.h utsname.h wait.h
├── init
│ └── main.c
├── kernel
│ ├── asm.s exit.c fork.c mktime.c panic.c
│ ├── printk.c sched.c signal.c sys.c system_calls.s
│ ├── traps.c vsprintf.c
│ ├── blk_drv
│ │ ├── blk.h floppy.c hd.c ll_rw_blk.c ramdisk.c
│ ├── chr_drv
│ │ ├── console.c keyboard.S rs_io.s
│ │ ├── serial.c tty_io.c tty_ioctl.c
│ ├── math
│ │ ├── math_emulate.c
├── lib
│ ├── close.c ctype.c dup.c errno.c execve.c _exit.c
│ ├── malloc.c open.c setsid.c string.c wait.c write.c
├── Makefile
├── mm
│ ├── memory.c page.s
└── tools
└── build.c
Linux_source_dir/Documentation/*
เคอร์เนล Linux Newbiesเป็นทรัพยากรที่ยอดเยี่ยม
ฉันขอแนะนำให้คุณอ่าน " เคอร์เนลลินุกซ์ " โดย Greg Kroah-Hartman และ "การทำความเข้าใจเคอร์เนล Linux " โดย Robert Love ต้องอ่าน :)
ไดรเวอร์อุปกรณ์ Linuxเป็นอีกแหล่งข้อมูลที่ดี มันจะทำให้คุณมีวิธีอื่นในการทำงานด้านใน จากคำนำ:
นี่คือหนังสือเกี่ยวกับการเขียนไดรเวอร์อุปกรณ์สำหรับระบบ Linux นั่นเป็นเป้าหมายที่คุ้มค่าแน่นอน การไหลของผลิตภัณฑ์ฮาร์ดแวร์ใหม่นั้นไม่น่าจะช้าลงทุกเวลาเร็ว ๆ นี้และใครบางคนกำลังจะต้องทำให้โปรแกรมเบ็ดเตล็ดใหม่ ๆ เหล่านั้นทำงานกับ Linux ได้ แต่หนังสือเล่มนี้ยังเกี่ยวกับวิธีการทำงานของเคอร์เนล Linux และวิธีปรับการทำงานให้สอดคล้องกับความต้องการหรือความสนใจของคุณ Linux เป็นระบบเปิด ด้วยหนังสือเล่มนี้เราหวังว่าจะเปิดกว้างและเข้าถึงชุมชนนักพัฒนาขนาดใหญ่ได้มากขึ้น
Linux Kernel 2.4 Internalsเป็นแหล่งข้อมูลออนไลน์อื่นที่น่าสนใจ ดูเหมือนจะใช้วิธี 'กราวด์อัพ' สวยเริ่มต้นด้วยการบูท นี่คือ TOC:
และเพื่อให้มันดียิ่งขึ้นจึงมีการพัฒนาเคอร์เนล Linux รุ่นที่สามโดย Robert Love out และSlashdot ได้ตรวจสอบ
เริ่มต้นด้วย Linux Kernel Primer โดย Claudia Salzberg และคณะ เป็นการเริ่มต้นที่ดีสำหรับผู้เริ่มต้น หนังสือของ Robert Love ไม่ใช่หนังสือที่ควรเริ่มต้นด้วยแน่นอน หนังสือเล่มหลังอยู่เหนือระดับกลาง