Chapter 19

Kernel Contribution

Chapter 19: Linux Kernel Development and Community Contribution

Submitting a patch to the Linux kernel is a technical milestone for many engineers. The kernel community is large and process-driven, yet welcoming to newcomers who follow established conventions. This chapter covers the full pipeline: acquiring sources, building the kernel, understanding coding standards, checking code with checkpatch.pl, generating patches with git format-patch, sending them to the LKML via git send-email, and earning maintainer acceptance.

1. Getting Started: Barriers and Opportunities

The fundamental difference between kernel and application development is the execution environment: kernel code runs in privileged mode with no standard library, no memory protection, and no floating-point arithmetic. A null pointer dereference does not produce a segfault โ€” it triggers a kernel panic. This demands deep understanding of hardware and OS internals.

Despite the high bar, the kernel community offers many contributor-friendly entry points. You do not have to start by writing a new driver or implementing a new subsystem. Recommended beginner paths include:

Why contribute: Your code runs on billions of devices worldwide. Kernel Newbies data shows most contributors who get their first patch accepted keep contributing. A commit record in Linus's tree is also a powerful resume entry.

2. Acquiring the Kernel Source

The Linux kernel has multiple official trees. Beginners should understand what each is for:

Tree URL Purpose
mainline kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Linus's mainline, releases rc versions
linux-next kernel.org/pub/scm/linux/kernel/git/next/linux-next.git Integration of all subsystem next branches; base your patches here
stable kernel.org/pub/scm/linux/kernel/git/stable/linux.git Stable release maintenance and backported critical fixes
Subsystem trees Maintained by respective maintainers e.g. net-next (networking), drm-next (GPU)
# ๅ…‹้š† linux-next๏ผˆไฝฟ็”จ --depth=1 ่Š‚็œๆ—ถ้—ด๏ผŒๅฎŒๆ•ดๅކๅฒ็บฆ 4GB๏ผ‰
git clone --depth=1 \
  https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git \
  linux-next
cd linux-next

# ๅฆ‚ๆžœๅŽ็ปญ้œ€่ฆๅฎŒๆ•ดๅކๅฒ๏ผˆ็”จไบŽ git log / git blame๏ผ‰
git fetch --unshallow

# ๆทปๅŠ  stable ๆ ‘ไฝœไธบ่ฟœ็จ‹ไป“ๅบ“
git remote add stable \
  https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

# ๆŸฅ็œ‹ tag ๅˆ—่กจ๏ผˆๅ†…ๆ ธ็‰ˆๆœฌๅท๏ผ‰
git tag -l 'v6.*' | sort -V | tail -20

3. Building the Kernel

Install Build Dependencies

# Debian / Ubuntu
sudo apt-get install -y \
  build-essential libelf-dev libssl-dev \
  flex bison bc dwarves pahole \
  libncurses-dev pkg-config

# Fedora / RHEL
sudo dnf install -y \
  gcc make flex bison elfutils-libelf-devel \
  openssl-devel ncurses-devel bc dwarves

Kernel Configuration

# ๆ–นๅผ1๏ผšๅ›พๅฝขๅŒ– TUI ่œๅ•๏ผˆๆŽจ่ๆ–ฐๆ‰‹๏ผ‰
make menuconfig

# ๆ–นๅผ2๏ผšไฝฟ็”จๆžถๆž„้ป˜่ฎค้…็ฝฎ๏ผˆ้€‚ๅˆๅฟซ้€Ÿ้ชŒ่ฏ่กฅไธ๏ผ‰
make defconfig

# ๆ–นๅผ3๏ผšๅŸบไบŽๅฝ“ๅ‰่ฟ่กŒๅ†…ๆ ธ็š„้…็ฝฎ๏ผˆๅช็ผ–่ฏ‘ๅทฒๅŠ ่ฝฝๆจกๅ—๏ผŒ้€Ÿๅบฆๆœ€ๅฟซ๏ผ‰
make localmodconfig
# ไน‹ๅŽๆŠŠๅฝ“ๅ‰ๅ†…ๆ ธ config ๅคๅˆถ่ฟ‡ๆฅ
cp /boot/config-$(uname -r) .config
make olddefconfig   # ๅฏนๆ–ฐๅขž้€‰้กน้‡‡็”จ้ป˜่ฎคๅ€ผ

# ไป…ไฟฎๆ”นๅ•ไธช้…็ฝฎ้กน๏ผˆไธๆ‰“ๅผ€่œๅ•๏ผ‰
./scripts/config --enable  CONFIG_DEBUG_INFO
./scripts/config --disable CONFIG_SECURITY_SELINUX
make olddefconfig

Build and Install

# ๅนถ่กŒ็ผ–่ฏ‘๏ผˆnproc ่พ“ๅ‡บ CPU ๆ ธๅฟƒๆ•ฐ๏ผŒ็ผ–่ฏ‘ๆ—ถ้—ด้šๆœบๅ™จ่€Œๅผ‚๏ผŒ็บฆ10ๅˆ†้’Ÿๅˆฐ1ๅฐๆ—ถ๏ผ‰
make -j$(nproc)

# ็”จ ccache ๅŠ ้€ŸไบŒๆฌก็ผ–่ฏ‘๏ผˆ้ฆ–ๆฌก็ผ–่ฏ‘ๅŽๆ•ˆๆžœๆ˜Žๆ˜พ๏ผ‰
sudo apt-get install -y ccache
CC="ccache gcc" make -j$(nproc)

# ๅฎ‰่ฃ…ๅ†…ๆ ธๆจกๅ—
sudo make modules_install

# ๅฎ‰่ฃ…ๅ†…ๆ ธ้•œๅƒ๏ผˆๅŒๆ—ถๆ›ดๆ–ฐ initramfs ๅ’Œ GRUB๏ผ‰
sudo make install
# ๆˆ–ๆ‰‹ๅŠจๅคๅˆถ
sudo cp arch/x86/boot/bzImage /boot/vmlinuz-$(make kernelrelease)
sudo update-grub

# ้ชŒ่ฏๆ–ฐๅ†…ๆ ธ็‰ˆๆœฌ
cat include/generated/utsrelease.h

Note: Always test self-compiled kernels in a VM or spare machine โ€” never replace the kernel on a production system. If the new kernel fails to boot, select the previous kernel in the GRUB menu to roll back.

4. Kernel Coding Standards

The kernel coding style document lives at Documentation/process/coding-style.rst and is mandatory reading for all contributors. Patches that violate these rules will be rejected by maintainers โ€” often without explanation.

Indentation and Line Length

/* ๅ†…ๆ ธไฝฟ็”จ TAB ็ผฉ่ฟ›๏ผŒๅฎฝๅบฆไธบ 8 ไธชๅญ—็ฌฆ๏ผˆ้ž็ฉบๆ ผ๏ผ๏ผ‰ */
/* ่กŒ้•ฟ้™ๅˆถไปŽๅކๅฒ็š„ 80 ๅญ—็ฌฆๆ”พๅฎฝๅˆฐไบ† 100 ๅญ—็ฌฆ */

/* ๆญฃ็กฎ */
int kernel_function(struct device *dev, unsigned long flags)
{
	if (flags & SOME_FLAG) {
		do_something(dev);
		return 0;
	}
	return -EINVAL;
}

/* ้”™่ฏฏ๏ผšไฝฟ็”จ็ฉบๆ ผ็ผฉ่ฟ› */
int bad_function(void) {
    return 0;  /* ่ฟ™ๆ˜ฏ็ฉบๆ ผ๏ผŒไธๆ˜ฏ TAB */
}

Brace Placement

/* ๅ‡ฝๆ•ฐไฝ“็š„ๅทฆ่Šฑๆ‹ฌๅท็‹ฌๅ ไธ€่กŒ๏ผˆK&R ้ฃŽๆ ผ็š„ๅ†…ๆ ธๅ˜ไฝ“๏ผ‰ */
int my_function(int arg)
{
	/* ๅ‡ฝๆ•ฐไฝ“ */
}

/* ๆŽงๅˆถ่ฏญๅฅ๏ผˆif/for/while๏ผ‰ๅทฆ่Šฑๆ‹ฌๅทๅœจๅŒไธ€่กŒ */
if (condition) {
	do_something();
} else {
	do_other();
}

/* ๅ•่กŒ if ไธ่ฆๅŠ ่Šฑๆ‹ฌๅท๏ผŒ้™ค้ž else ๅˆ†ๆ”ฏ้œ€่ฆ */
if (err)
	return err;

Naming Conventions

Legitimate Use of goto

/* ๅ†…ๆ ธไธญ goto ็”จไบŽ้”™่ฏฏ่ทฏๅพ„ๆธ…็†๏ผŒๆ˜ฏๆŽจ่ๅšๆณ• */
int probe_device(struct platform_device *pdev)
{
	struct my_priv *priv;
	int ret;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		ret = -ENOMEM;
		goto err_alloc;
	}

	ret = request_irq(priv->irq, my_irq_handler, 0, "mydev", priv);
	if (ret)
		goto err_irq;

	ret = register_device(priv);
	if (ret)
		goto err_register;

	return 0;

err_register:
	free_irq(priv->irq, priv);
err_irq:
	/* devm_kzalloc ่‡ชๅŠจ้‡Šๆ”พ๏ผŒๆ— ้œ€ๆ‰‹ๅŠจ free */
err_alloc:
	return ret;
}

5. Finding Places to Contribute

drivers/staging

The drivers/staging/ directory contains drivers not yet meeting mainline quality standards. Each driver has a TODO file explicitly listing what needs to be fixed โ€” the best entry point for beginners.

# ๅˆ—ๅ‡บๆ‰€ๆœ‰ staging ้ฉฑๅŠจๅŠๅ…ถ TODO ๆ–‡ไปถ
ls drivers/staging/
cat drivers/staging/greybus/TODO

# ็”จ checkpatch ๆ‰ซๆๆŸไธช staging ้ฉฑๅŠจ
scripts/checkpatch.pl --strict -f drivers/staging/greybus/*.c

# ๆœ็ดข coding style ้—ฎ้ข˜๏ผˆๅ…ธๅž‹๏ผš็”จ printk ๆ›ฟไปฃ dev_err๏ผ‰
grep -rn "printk(" drivers/staging/greybus/ | grep -v "KERN_"

Using sparse for Type Annotation Checks

# ๅฎ‰่ฃ… sparse
sudo apt-get install -y sparse

# ๅช็ผ–่ฏ‘็›ฎๆ ‡้ฉฑๅŠจ๏ผˆไธ้œ€่ฆๅ…จ้‡็ผ–่ฏ‘๏ผ‰
make C=1 drivers/staging/greybus/

# C=2 ๅœจๆ‰€ๆœ‰ๆ–‡ไปถไธŠ่ฟ่กŒ sparse๏ผˆๅŒ…ๆ‹ฌๅทฒ็ป็ผ–่ฏ‘่ฟ‡็š„๏ผ‰
make C=2 drivers/staging/greybus/

# ๅธธ่ง sparse ่ญฆๅ‘Š๏ผš
# warning: incorrect type in argument
# warning: context imbalance in 'func' -- unexpected unlock

6. Preparing Your First Patch

Understand the Problem

Before touching any code, fully understand the problem. Use git log --oneline drivers/xxx/ to review change history, git blame to find the original authors, and read relevant kernel docs and comments. Confirm this is genuinely a bug or standards violation, not a misunderstanding of kernel APIs.

# ๅˆ›ๅปบๅทฅไฝœๅˆ†ๆ”ฏ๏ผˆๅˆ†ๆ”ฏๅๆ่ฟฐๅ…ทไฝ“ๆ”นๅŠจ๏ผŒไพฟไบŽ maintainer ่ฏ†ๅˆซ๏ผ‰
git checkout -b staging/greybus/fix-coding-style

# ็ผ–่พ‘ๆ–‡ไปถ๏ผŒๅšๆœ€ๅฐๅŒ–ใ€่š็„ฆ็š„ๆ”นๅŠจ
# ไธ€ไธช patch ๅชๅšไธ€ไปถไบ‹๏ผไธ่ฆๆŠŠๅคšไธชๆ— ๅ…ณๆ”นๅŠจๆททๅœจไธ€่ตท
vim drivers/staging/greybus/core.c

# ๅช็ผ–่ฏ‘็›ฎๆ ‡ๆจกๅ—้ชŒ่ฏๆ”นๅŠจไธๅผ•ๅ…ฅ็ผ–่ฏ‘้”™่ฏฏ
make -j$(nproc) drivers/staging/greybus/

# sparse ๆฃ€ๆŸฅ
make C=1 drivers/staging/greybus/

Running checkpatch.pl

# ๆฃ€ๆŸฅๆœ€ๆ–ฐไธ€ไธช commit๏ผˆๆœ€ๅธธ็”จๆ–นๅผ๏ผ‰
scripts/checkpatch.pl --strict -g HEAD

# ๆฃ€ๆŸฅไธ€ไธช .patch ๆ–‡ไปถ
scripts/checkpatch.pl --strict 0001-staging-greybus-fix-style.patch

# ๆฃ€ๆŸฅๆŸไธชๆบๆ–‡ไปถ๏ผˆไธ้œ€่ฆๅ…ˆ commit๏ผ‰
scripts/checkpatch.pl --strict -f drivers/staging/greybus/core.c

# ่พ“ๅ‡บ็คบไพ‹๏ผš
# WARNING: line over 100 characters
# ERROR: do not use assignment in if condition
# CHECK: 'foo' may be better written as 'bar'
# total: 0 errors, 1 warnings, 0 checks, 42 lines checked

Target: Before sending, aim for total: 0 errors, 0 warnings. CHECK-level hints (blue) are advisory โ€” fix them when reasonable but they are not mandatory.

Writing the Commit Message

git add drivers/staging/greybus/core.c
git commit
# commit message ๆ ผๅผ๏ผˆ้žๅธธ้‡่ฆ๏ผ๏ผ‰๏ผš
# ็ฌฌไธ€่กŒ๏ผšsubsystem: component: Short description (50ๅญ—็ฌฆไปฅๅ†…)
# ็ฉบ่กŒ
# ๆญฃๆ–‡๏ผš่งฃ้‡Šไธบไป€ไนˆๅš่ฟ™ไธชๆ”นๅŠจ๏ผˆWHY๏ผ‰๏ผŒ่€Œไธๆ˜ฏๅšไบ†ไป€ไนˆ๏ผˆWHAT๏ผŒไปฃ็ ๅทฒ็ป่ฏดๆ˜Ž๏ผ‰
# ็ฉบ่กŒ๏ผˆๅฆ‚ๆœ‰๏ผ‰
# ๆ ‡็ญพ่กŒ๏ผˆSigned-off-by ๆ˜ฏๅผบๅˆถ่ฆๆฑ‚๏ผ‰

staging: greybus: replace printk with dev_err for proper log context

Using raw printk() in device drivers loses the device context from
the log message, making it harder to correlate log entries with
specific devices in systems with multiple greybus instances.

Replace printk(KERN_ERR ...) calls with dev_err(dev, ...) which
automatically prepends the device name to the log output.

Signed-off-by: Your Name

Signed-off-by: Signed-off-by is the Developer's Certificate of Origin (DCO) declaration, confirming you have the right to submit this code. Patches without it are rejected outright. Use git commit -s to add it automatically.

7. Finding the Right Maintainer

The Linux kernel has hundreds of maintainers, each responsible for a specific subsystem. Finding the right maintainer and mailing list before sending is essential โ€” otherwise your patch will be ignored.

# get_maintainer.pl ๆ นๆฎๆ–‡ไปถ่ทฏๅพ„ๆˆ– patch ๅ†…ๅฎนๆŸฅๆ‰พ maintainer
# ่พ“ๅ‡บๆ ผๅผ๏ผšName  (role: maintainer/reviewer/...)

# ๅฏนๆœ€ๆ–ฐ็š„ commit ็”Ÿๆˆ patch ๅนถๆŸฅๆ‰พ maintainer
git format-patch -1 HEAD --stdout | scripts/get_maintainer.pl

# ๆˆ–็›ดๆŽฅๆŒ‡ๅฎšๆ–‡ไปถ
scripts/get_maintainer.pl --file drivers/staging/greybus/core.c

# ็คบไพ‹่พ“ๅ‡บ๏ผš
# Greg Kroah-Hartman  (maintainer:STAGING SUBSYSTEM)
# Johan Hovold  (reviewer:GREYBUS SUBSYSTEM)
# [email protected] (open list:STAGING SUBSYSTEM)
# [email protected] (open list:GREYBUS SUBSYSTEM)

The MAINTAINERS file in the kernel root is the maintainer database, containing M (maintainer), R (reviewer), L (mailing list), S (status), and F (file pattern) fields for each subsystem. Understanding this file helps you decide where to send your patch.

8. Sending the Patch

Generating .patch Files

# ็”Ÿๆˆๆœ€ๆ–ฐ 1 ไธช commit ็š„ patch๏ผˆ-1 ่กจ็คบๆœ€่ฟ‘ 1 ไธช๏ผ‰
git format-patch -1 HEAD

# ็”Ÿๆˆๅคšไธช commit ็š„ patch ็ณปๅˆ—๏ผˆ่‡ชๅŠจๆทปๅŠ ๅบๅทๅ‰็ผ€๏ผ‰
git format-patch -3 HEAD   # ๆœ€่ฟ‘ 3 ไธช commit

# ๅŠ  cover letter๏ผˆ่กฅไธ็ณปๅˆ—ไป‹็ป๏ผŒ--cover-letter ็”Ÿๆˆ 0000-cover-letter.patch๏ผ‰
git format-patch -3 HEAD --cover-letter

# ๆŒ‡ๅฎš่พ“ๅ‡บ็›ฎๅฝ•
git format-patch -1 HEAD -o /tmp/patches/

# ็”Ÿๆˆ็š„ๆ–‡ไปถ็คบไพ‹๏ผš
# 0001-staging-greybus-replace-printk-with-dev_err.patch

Configuring git send-email

# ๅฎ‰่ฃ… git send-email๏ผˆๅฏ่ƒฝ้œ€่ฆๅ•็‹ฌๅฎ‰่ฃ…๏ผ‰
sudo apt-get install -y git-email

# ~/.gitconfig ไธญ้…็ฝฎ SMTP๏ผˆไปฅ Gmail ไธบไพ‹๏ผ‰
git config --global sendemail.smtpserver smtp.gmail.com
git config --global sendemail.smtpserverport 587
git config --global sendemail.smtpencryption tls
git config --global sendemail.smtpuser [email protected]
# SMTP ๅฏ†็ ้€š่ฟ‡ git credential helper ็ฎก็†ๆˆ–ๅœจๅ‘ฝไปค่กŒ่พ“ๅ…ฅ

# ไปฅ่…พ่ฎฏไผไธš้‚ฎไธบไพ‹
git config --global sendemail.smtpserver smtp.exmail.qq.com
git config --global sendemail.smtpserverport 465
git config --global sendemail.smtpencryption ssl

Sending the Patch

# ๅ…ˆ็”จ --dry-run ้ข„่งˆ๏ผˆไธๅฎž้™…ๅ‘้€๏ผ‰
git send-email \
  --to [email protected] \
  --cc [email protected] \
  --dry-run \
  0001-staging-greybus-replace-printk-with-dev_err.patch

# ็กฎ่ฎคๆ— ่ฏฏๅŽๅŽปๆމ --dry-run ๅ‘้€
git send-email \
  --to [email protected] \
  --cc [email protected] \
  0001-staging-greybus-replace-printk-with-dev_err.patch

# ๅ‘้€ patch ็ณปๅˆ—๏ผˆcover letter + ๅคšไธช patch๏ผ‰
git send-email \
  --to [email protected] \
  --cc [email protected] \
  /tmp/patches/*.patch

Critical: Kernel patches must be sent as plain text with no HTML, and the mail client must not re-wrap lines. Thunderbird requires plain-text mode with format=flowed disabled. Gmail's web interface corrupts patch formatting โ€” strongly prefer git send-email.

9. LKML Etiquette

Writing a Cover Letter

A single patch usually does not need a cover letter, but a patch series (more than 2 patches) must include one explaining the overall intent. The cover letter subject line format is [PATCH 0/N] Subject; the body explains why you are making these changes, how you tested them, and any known limitations.

Responding to Review Feedback

Common Tag Meanings

Tag Meaning
Signed-off-by: Author certifies right to submit (DCO); also used by maintainers when forwarding
Reviewed-by: Reviewer confirms code is correct and recommends merging
Acked-by: Relevant party (e.g., subsystem maintainer) does not object without deep review
Tested-by: Tester verified the patch works on real hardware
Reported-by: Credits the person who reported the bug
Fixes: Points to the commit this patch fixes (format: Fixes: abcdef ("commit subject"))

Tracking Patch Status with patchwork

patchwork.kernel.org automatically archives patches sent to mailing lists and tracks their status (New / Under Review / Accepted / Rejected / Deferred). After sending, search patchwork by your name or patch subject to confirm correct archival.

10. Kernel Newbies and Learning Resources

The kernel community provides excellent learning and support channels for newcomers:

Action checklist: โ‘  Clone linux-next, โ‘ก find a checkpatch warning in drivers/staging/, โ‘ข fix it and verify with checkpatch, โ‘ฃ use get_maintainer.pl to find recipients, โ‘ค send the patch to the mailing list (even staging patches get real human review). Complete these five steps and you are officially a kernel contributor.

  Previous
  โ† Ch18: Mini Shell


  Next
  Ch20: Final Project โ†’
Rate this chapter
4.6  / 5  (10 ratings)

๐Ÿ’ฌ Comments