Tampilkan postingan dengan label kernel. Tampilkan semua postingan
Tampilkan postingan dengan label kernel. Tampilkan semua postingan

9.4.09

Tutorial pengembangan sistem embedded Linux

LinuxDevices has posted the second in a series of tutorials on embedded Linux system development written by ARM Linux kernel hackers Vincent Sanders and Daniel Silverstone of the UK-based development firm, Simtec Electronics. Part Two explains how to construct a simple web server with a command shell on the console.

Part one of the series, written by Simtec Senior Software Engineer Sanders and Simtec Software Engineer Silverstone, walked new Linux developers through the construction of a simple embedded Linux system. Principal sections of the new web server tutorial include:
  • Automated, reproducible, reliable building -- Shortening the edit, build, and test cycle via automation, including use of a Revision Control System (RCS), or for larger systems, a full build manager

  • Scripting builds and common tasks -- using a shell script to add functions to copy executables and their library dependencies, configure a DHCP
    client, and copy kernel modules from the host to the target

  • Creating a web server's file system -- Choosing and configuring a web server, acquiring the Thttpd binary, and testing with the QEMU emulator
The remaining tutorials, to be published in the coming weeks, include:
  • Building an embedded Linux web kiosk
  • Building an ARM-based embedded Linux web kiosk
  • Improving an embedded Linux system
  • Deploying embedded Linux systems
The new web server tutorial is available here: Tutorial: Web Server Embedded Linux System

18.11.08

Akses Memori PCI

(bagian akhir dari 7 artikel - ke artikel utama)

Untuk mengakses memori PCI milik sebuah devais, harus digunakan beberapa fungsi umum dan tidak disarankan untuk mengakses alamat memori secara langsung. Berbagai hardware mempunyai cara berbeda saat mengakses bus PCI. Jika digunakan fungsi umum, maka driver PCI yang dibuat akan dapat dijalankan di berbagai sistem linux (sehingga menjadi portabel)

Untuk membaca data dari bus PCI digunakan fungsi-fungsi berikut ini:


int pci_read_config_byte (struct pci_dev * dev , int where , u8 * val );
int pci_read_config_word(struct pci_dev *dev, int where, u16 *val);
int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val);

sedangkan untuk menuliskan data digunakan fungsi-fungsi ini:
int pci_write_config_byte(struct pci_dev *dev, int where, u8 val);
int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);

Fungsi-fungsi di atas memungkinkan penulisan data berukuran 8, 16 atau 32 bit ke lokasi tertentu yang ditempat devais PCI. Jika diinginkan mengakses lokasi memori suatu devais PCI yang belum diinisialisasi oleh inti Linux PCI, maka dapat digunakan fungsi-fungsi berikut ini (yang terdapat dalam kode inti pci_hotplug:


int pci_read_config_byte_nodev(struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u8 *val);
int pci_read_config_word_nodev(struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u16 *val);
int pci_read_config_dword_nodev(struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u32 *val);
int pci_write_config_byte_nodev(struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u8 val);
int pci_write_config_word_nodev(struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u16 val);
int pci_write_config_dword_nodev(struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u32 val);

Contoh cara membaca dan menulis memori PCI yang dilakukan melalui driver dapat dilihat pada driver USB OHCI driver pada berkas drivers/usb/host/usb-ohci.c:


pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
if (latency) {
pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
if (limit && limit < latency) {
dbg("PCI latency reduced to max %d", limit);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
ohci->pci_latency = limit;
} else {
/* it might already have been reduced */
ohci->pci_latency = latency;
}
}

14.11.08

Akses Memori I/O

(bagian 6 dari 7 artikel - ke artikel utama)

Tidak seperti sistem embedded umumnya, mengakses memori I/O di linux tak dapat dilakukan secara langsung. Sebabnya karena Linux mempunyai tipe dan peta memori yang sangat beragam dan Linux dirancang untuk jalan di beragam prosesor. Untuk mengakses memori I/O secara portabel, harus digunakan fungsi ioremap() untuk meminta jatah akses dan fungsi iounmap() untuk melepas jatah akses.

ioremap() didefinisikan sebagai berikut:

void __iomem *ioremap(unsigned long offset, unsigned long size);

Saat memanggil fungsi dua parameter dipassing. Pertama adalah offset awal dari region memori yang akan diakses dan kedua adalah ukuran region dalam byte. Hasil pemanggilan fungsi tidak dapat digunakan sebagai lokasi memori untuk ditulis baca secara langsung. Hasil pemanggilan fungsi itu merupakan token yang harus dipassing ke berbagai fungsi untuk membaca dan menulis data.

Berikut ini adalah fungsi-fungsi yang digunakan untuk membaca dan menulis data menggunakan memori yang teladh dipetakan oleh ioremap():

unsigned char  readb(const volatile void __iomem *addr);  /* read 8 bits */
unsigned short readw(const volatile void __iomem *addr); /* read 16 bits */
unsigned int readl(const volatile void __iomem *addr); /* read 32 bits */
void writeb (unsigned char value, volatile void __iomem *addr); /* write 8 bits */
void writew (unsigned short value, volatile void __iomem *addr); /* write 16 bits */
void writel (unsigned int value, volatile void __iomem *addr); /* write 32 bits */

Setelah memori selesai diakses, fungsi iounmap() harus dipanggil agar yang lain dapat mengakses alamat memori I/O tersebut.

13.9.08

Penataan Posisi Data

(bagian 5 dari 7 artikel - ke artikel utama)

Kompailer gcc menata setiap field (ruas) dari struktur data ke lokasi memori yang dianggapnya akan mempercepat eksekusi program. Sebagai contoh perhatikan program berikut beserta outputnya:
#include <stdio.h>
#include <stddef.h>

struct foo {
char a;
short b;
int c;
};

#define OFFSET_A offsetof(struct foo, a)
#define OFFSET_B offsetof(struct foo, b)
#define OFFSET_C offsetof(struct foo, c)

int main()
{
printf ("offset A = %d\n",OFFSET_A);
printf ("offset B = %d\n",OFFSET_B);
printf ("offset C = %d\n",OFFSET_C);
return 0;
}
Output program ini adalah:
offset A = 0
offset B = 2
offset C = 4
Output program menunjukkan bahwa kompailer menata ruas variabel b dan c pada struktur foo pada alamat memori genap. Ini tidak baik JIKA kita ingin menuliskan satu per satu data pada struktur itu ke SATU alamat memori. Biasanya struktur data sebuah driver mempunyai lokasi byte berurutan. Oleh karena itu atribut gcc ((packed)) digunakan untuk meminta kompailer agar tidak membuat "lubang memori" dalam struktur data. (Perhatikan bahwa A berukuran satu byte, tapi B terletak di offset ke-2 sehingga offset ke-1 kosong dan tidak digunakan).

Jika struktur foo diubah menggunakan atribut packed:
struct foo {
char a;
short b;
int c;
} __attribute__((packed));
Maka output program akan menjadi sebagai berikut:
offset A = 0
offset B = 1
offset C = 3
Sekarang tidak ada lagi lubang memori di dalam struktur (offset ke-1 ditempati variabel b).

Atribut packed dapat digunakan terhadap seluruh struktur, seperti contoh di atas, atau digunakan terhadap ruas tertentu.

Sebagai contoh, struktur usb_ctrlrequest pada include/usb.h didefinisikan sebagai berikut:
struct usb_ctrlrequest {
__u8 bRequestType;
__u8 bRequest;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
} __attribute__ ((packed));
untuk memastikan seluruh struktur tidak mempunyai lubang memori, sehingga datanya dapat langsung ditulis ke port USB.

Namun struktur usb_endpoint_descriptor didefinisikan seperti berikut ini:
struct usb_endpoint_descriptor {
__u8 bLength __attribute__ ((packed));
__u8 bDescriptorType __attribute__ ((packed));
__u8 bEndpointAddress __attribute__ ((packed));
__u8 bmAttributes __attribute__ ((packed));
__le16 wMaxPacketSize __attribute__ ((packed));
__u8 bInterval __attribute__ ((packed));
__u8 bRefresh __attribute__ ((packed));
__u8 bSynchAddress __attribute__ ((packed));
unsigned char *extra ; /* Extra descriptors */
int extralen;
};
agar bagian awal struktur tidak mempunyai lubang memori sehingga dapat digunakan langsung untuk meletakkan data yang dibaca dari USB, tapi ruas extra dan extralen dibiarkan untuk ditata oleh kompailer agar akses data oleh program menjadi lebih cepat.

26.8.08

Masalah Endian

(bagian 4 dari 7 artikel - ke artikel utama - ke bagian 5)

Processors store internal data in one of two ways: little-endian or big-endian. Little-endian processors store data with the right-most bytes (those with a higher address value) being the most significant, while big-endian processors store data with the left-most bytes (those with a lower address value) being the most significant.

For example, the table below shows how the decimal value 684686 is stored in a 4-byte integer on the two different processor types (684686 decimal = a728e hex = 00000000 00001010 01110010 10001110 binary)

AddressBig-EndianLittle-Endian
00000000010001110
1 0000101001110010
20111001000001010
31000111000000000

The Intel i386 family are little-endian machines, whereas the SPARC and 68k processors are big-endian. The Alpha, IA-64 and PowerPC processors can be run in either little- or big-endian mode; for Linux the Alpha and IA-64 are typically run in little-endian mode and the PowerPC is run in big-endian mode. The ARM processor can be either, depending on the specific ARM chip being used, the original ARMs were little-endian but for devices designed for network processing they are usually big-endian.

Because of the different endian types of processors, you need to be aware of data you receive from external sources and the order in which it appears. For example, the USB specification dictates that all multibyte data fields are in little-endian form. So if you have a USB driver that reads a multibyte field from the USB connection, you need to convert that data into the processor's native format. Code that assumes the processor is little-endian could ignore the data format coming from the USB connection successfully. But this same code would not work on PowerPC and is the leading cause of drivers that are broken on different platforms. Conversely most networking data is defined in terms of big endian data structures.

Thankfully, there are a number of helpful macros that have been created to make this an easy task. All of the following macros can be found in the asm/byteorder.h header file.

To convert from the processor's native format into little-endian form you can use the following functions:

__le64 cpu_to_le64(u64);
__le32 cpu_to_le32(u32);
__le16 cpu_to_le16(u16);

To convert from little-endian format into the processor's native format you should use these functions:

u64 le64_to_cpu(__le64);
u32 le32_to_cpu(__le32);
u16 le16_to_cpu(__le16);

For big-endian forms, the following functions are available:

__be64 cpu_to_be64(u64);
__be32 cpu_to_be32(u32);
__be16 cpu_to_be16(u16);
u64 be64_to_cpu(__be64);
u32 be32_to_cpu(__be32);
u16 be16_to_cpu(__be16);

If you have a pointer to the value to convert, then you should use the following functions:

__le64 cpu_to_le64p(u64 *);
__le32 cpu_to_le32p(u32 *);
__le16 cpu_to_le16p(u16 *);
u64 le64_to_cpup(__le64 *);
u32 le32_to_cpup(__le32 *);
u16 le16_to_cpup(__le16 *);
__be64 cpu_to_be64p(u64 *);
__be32 cpu_to_be32p(u32 *);
__be16 cpu_to_be16p(u16 *);
u64 be64_to_cpup(__be64 *);
u32 be32_to_cpup(__be32 *);
u16 be16_to_cpup(__be16 *);

If you want to convert the value within a variable and store the modified value in the same variable (in situ), then you should use the following functions:

void cpu_to_le64s(u64 *);
void cpu_to_le32s(u32 *);
void cpu_to_le16s(u16 *);
void le64_to_cpus(u64 *);
void le32_to_cpus(u32 *);
void le16_to_cpus(u16 *);
void cpu_to_be64s(u64 *);
void cpu_to_be32s(u32 *);
void cpu_to_be16s(u16 *);
void be64_to_cpus(u64 *);
void be32_to_cpus(u32 *);
void be16_to_cpus(u16 *);

As stated before, the USB protocol is in little-endian format. The code snippet from drivers/usb/serial/visor.c below shows how a structure is read from the USB connection and then converted into the proper CPU format.

struct visor_connection_info *connection_info;
/* send a get connection info request */
usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_GET_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000,
transfer_buffer, 0x12, 300);
connection_info = (struct visor_connection_info *)transfer_buffer;
num_ports = le16_to_cpu(connection_info->num_ports);

16.8.08

Masalah memori

(bagian 3 dari 7 artikel - ke artikel utama - ke bagian 4)

Seperti dijelaskan di Tipe data kernel internal dari contoh yang diambil dari berkas drivers/char/serial.c, program dapat meminta alokasi halaman memori ke kernel. Ukuran halaman memori tidak selalu 4KB (seperti pada arsitektur i386). Karena itu, untuk merujuk suatu halaman memori, harus digunakan parameter PAGE_SHIFT dan PAGE_SIZE.

PAGE_SHIFT adalah banyaknya pergeseran bit ke kiri (bit shift left) agar diperoleh nilai PAGE_SIZE. Arsitektur yang berbeda mempunyai nilai parameter yang berbeda, seperti yang ditampilkan pada tabel di bawah ini.

ArsitekturPAGE_SHIFTPAGE_SIZE
i386124K
MIPS124K
Alpha138K
m68k124K
m68k138K
ARM124K
ARM1416K
ARM1532K
IA-64124K
IA-64138K
IA-641416K
IA-641664K

Bahkan terdapat arsitektur yang mempunyai ukuran halaman yang bervariasi. Perbedaan ini bisa disebabkan perbedaan opsi (seperti pada IA-64) atau perbedaan varian prosesor (seperti pada ARM). Potongan program drivers/usb/class/audio.c di bawah ini memperlihatkan bagaimana kedua parameter: PAGE_SHIFT dan PAGE_SIZE digunakan untuk akses memori:
static int dmabuf_mmap(...)
{
size >>= PAGE_SHIFT;
for(nr = 0; nr < size; nr++)
if (!db->sgbuf[nr])
return -EINVAL;
db->mapped = 1;
for (nr = 0; nr < size; nr++) {
unsigned long pfn;

pfn = virt_to_phys(db->sgbuf[nr]) >> PAGE_SHIFT;
if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, prot))
return -EAGAIN;
start += PAGE_SIZE;
}
return 0;
}

13.8.08

Tipe data kernel internal

(bagian 2 dari 7 artikel - ke artikel utama - bagian 3)

Ketika membuat program yang portabel, perlu diperhatikan benar jumlah byte dari variabel yang digunakan di dalam program. Berbagai prosesor mempunyai jumlah byte berbeda untuk tipe data int dan long. Ada juga perbedaan cara menentukan apakah variabel signed atau unsigned. Jadi kalau program yang dibuat harus menggunakan jumlah bit tertentu, dan harus tegas signed atau unsigned, maka Anda harus menggunakan tipe data yang sudah built-in. Typedefs berikut ini dapat dipakai di sembarang tempat dalam program kernel dan didefinisikan dalam berkas header linux/types.h.

 u8    unsigned byte (8 bit)
u16 unsigned word (16 bit)
u32 unsigned 32-bit
u64 unsigned 64-bit

s8 signed byte (8 bit)
s16 signed word (16 bit)
s32 signed 32-bit
s64 signed 64-bit

Sebagai contoh, driver i2c mempunyai beberapa fungsi yang digunakan untuk mengirim dan menerima data melalui bus i2c:

s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);
s32 i2c_smbus_read_byte_data(struct i2c_client *client,
u8 command);

s32 i2c_smbus_write_byte_data(struct i2c_client *client,
u8 command, u8 value);

Semua fungsi di atas mempunyai output nilai 32 bit signed dan mempunyai input nilai 8 bit unsigned untuk semua parameternya. Dengan menggunakan tipe data seperti ini, program di atas portabel untuk semua prosesor.

Jika ingin agar variabel dapat diakses melalui program di wilayah user (user-space), maka harus digunakan tipe data exportabel di bawah ini. Contoh tipe data ini terdapat dalam struktur data yang di-passing saat memanggil perintah ioctl(). Tipe data ini didefinisikan di berkas header linux/types.h.

__u8   unsigned byte (8 bit)
__u16 unsigned word (16 bit)
__u32 unsigned 32-bit
__u64 unsigned 64-bit

__s8 signed byte (8 bit)
__s16 signed word (16 bit)
__s32 signed 32-bit
__s64 signed 64-bit

Sebagai contoh, berkas header usbdevice_fs.h mempunyai beberapa struktur data untuk digunakan berkomunikasi dengan piranti USB (USB device) melalui program di wilayah user (user space). Berikut adalah definisi ioctl yang digunakan mengirim pesan kontrol USB ke piranti:

struct usbdevfs_ctrltransfer {
__u8 requesttype;
__u8 request;
__u16 value;
__u16 index;
__u16 length;
__u32 timeout; /* in milliseconds */
void *data;
};
#define USBDEVFS_CONTROL_IOWR('U', 0,
# struct usbdevfs_ctrltransfer)

Pada mesin 64-bit, ada satu hal yang sering menimbulkan problem yaitu bahwa jumlah byte pointer tidak sama dengan jumlah byte unsigned integer. Jumlah byte pointer sama dengan unsigned long seperti terlihat pada get_zeroed_page():

extern unsigned long FASTCALL
(get_zeroed_page(unsigned int gfp_mask))

Fungsi get_zeroed_page() membuat halaman memori kosong (free memory) yang isinya sudah dinolkan semua. Fungsi ini mempunyai output unsigned long yang harus diubah (typecast) ke tipe data lain yang sesuai. Potongan program drivers/char/serial.c dalam fungsi rs_open() berikut ini memperlihatkan caranya (catatan: kode ini dari kernel 2.4.x).

static unsigned char *tmp_buf;
unsigned long page;

if (!tmp_buf) {
page = get_zeroed_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
if (tmp_buf)
free_page(page);
else
tmp_buf = (unsigned char *)page;
}
Terdapat beberapa tipe data kernel yang dapat digunakan sebagai pengganti tipe data unsigned long, misalnya pid_t, key_t, gid_t, size_t, ssize_t, ptrdiff_t, time_t, clock_t, dan caddr_t. Gunakan tipe data ini untuk menghindari permasalahan portabilitas.

9.8.08

Membuat driver yang portabel

(bagian 1 dari 7 artikel - ke bagian 2)

Hampir semua driver Linux dapat berjalan di semua jenis prosesor. Agar bisa seperti itu, driver harus ditulis mengikuti aturan tertentu, termasuk misalnya menggunakan tipe variabel tertentu, tidak berasumsi tentang ukuran halaman memori, dan mengakses alamat device menggunakan interface tertentu. Secara rinci aturan-aturan itu adalah sebagai berikut.

Jika aturan-aturan ini ditaati, maka program yang dihasilkan akan bisa berjalan di semua prosesor. Aturan inipun sebaiknya diperhatikan ketika mendebug driver yang hanya jalan di satu platform.

Untuk membuat driver portabel, perlu dipelajari kode-kode kernel dan driver yang sudah diketahui bisa jalan di berbagai platform. Hal ini bisa dilakukan karena Linux bersifat open source (kode terbuka) sehingga siapapun bisa mempelajari kode sumber yang ada.

(disadur dari: Writing Portable Drivers)

17.7.08

Kernel Linux 2.6.26 untuk embedded system

Kernel baru sudah keluar. Proses pembuatan memakan waktu tiga bulan. Linux 2.6.26 memiliki beberapa fitur: read only bind mount, KVM port untuk sistem komputer "besar", support USB webcam, WiFi 802.11s mesh, built-in support untuk debug kernel secara remot, dan perbaikan dukungan arsitektur embedded.

Peluncuran kernel terbaru ini diumumkan oleh Linus Torvalds hari Minggu 13 Juli 2008. Kernel stabil ini mempunyai kode sumber sebesar 330MB dikompresi bzip2 menjadi 48.3MB. Bagi developer sistem embedded terdapat perbaikan dukungan untuk chip dan board tertentu, ditambah fitur menarik "yang luar biasa", misalnya built-in support untuk debug kernel secara remot (remote debugging) menggunakan KGDB.



Opsi Kernel Hacking pada make menuconfig


Seperti biasa, Kernel Newbies telah menampilkan detil fitur kernel baru ini di sini. Hal-hal menarik bagi para developer sistem embedded adalah:
  • Built-in support untuk debug jarak jauh menggunakan KGDB
  • Port KVM untuk Itanium (IA64), S390, dan PowerPC 440, plus banyak fitur KVM baru misalnya task switching perangkat keras x86
  • USB Video Class driver untuk dukungan webcam yang lebih baik.
  • Perbaikan pada 802.11n, support jaringan mesh 802.11s menggunakan Open80211s
  • Read only bind mount (apa sih ini?)
  • Perbaikan dokumentasi untuk opsi penjadwalan real-time
  • Perbaikan dukungan EXT4 (masih "eksperimental")
Kernel baru juga memperbaiki dukungan terhadap beberapa arsitektur khusus, termasuk di antaranya:
  • Dukungan nyata untuk:
  • Frequency scaling, NO_HZ pada Blackfin
  • Kernel preemption pada ColdFire
  • Banyak driver baru maupun perbaikan driver yang ada
  • Dukungan awal Radeon r500
  • Driver untuk PXA3xx audio dan NAND controller
  • Fitur manajemen daya untuk Asus EEE PC (kontrol kipas hwmon, backlight)
  • Dukungan flash pada Atmel AT25DF641 SPI
  • Hardware ECC controller pada Atmel AT91SAM9263 dan AT91SAM9260
Versi terbaru kernel dapat diketahui dengan menjalankan perintah di konsol/terminal GNU/Linux: finger linux at kernel.org, atau finger linux@kernel.org. Kernel 2.6.26 dapat diunduh melalui ftp di sini (berkas sig di sini) dan di sini change log.

Sumber asli: LinuxDevices.com

15.7.08

Sekilas kernel Linux (4): Subsistem utama

(Bagian 4 dari 4 artikel - ke artikel utama)

Secara garis besar, komponen utama kernel Linux dapat dibayangkan dengan model pada Gambar 1.

System call interface

Antarmuka pemanggilan sistem atau system call interface (SCI) merupakan lapisan tipis yang menyediakan cara-cara pemanggilan fungsi-fungsi kernel oleh proses/program di wilayah user. Antarmuka ini bisa berbeda-beda tergantung arsitektur meskipun berada dalam keluarga prosesor yang sama. SCI sebenarnya merupakan pelayanan multipleksi/demultipleksi pemanggilan fungsi. Implementasi SCI dapat dijumpai di kernel Linux pada direktori ./linux/kernel sedangkan bagian yang berbeda berdasarkan arsitektur dapat dijumpai di ./linux/arch.

Process management


Apakah itu kernel?
Seperti tampak pada Gambar 1, kernel tidak lebih dari manajer sumber daya. Sumber daya yang dikelola bisa berupa proses, memori atau perangkat keras. Kernel mengatur dan membagi akses sumber daya yang diakses banyak user. User yang dimaksud bisa program di kernel atau aplikasi di wilayah lebih tinggi.

Manajemen proses (process management) adalah bagian yang menjalankan proses. Pada kernel, proses ini disebut thread (thread dalam bahasa Inggris berarti benang) dan merupakan virtualisasi individual dari prosesor (kode thread, data, stack, dan register CPU). Pada wilayah user, istilah proses lebih sering digunakan tetapi dalam implementasinya proses dan thread di Linux tidaklah dibedakan (di wilayah user istilah thread digunakan untuk proses yang dapat berjalan bersamaan dengan thread/proses lain, misalnya pada program yang mengimplementasikan timer). Kernel menyediakan antarmuka program aplikasi (application program interface, API) melalui SCI untuk membuat proses baru (fork, exec, atau fungsi Portable Operating System Interface [POSIX]), menghentikan sebuah proses (kill, exit), berkomunikasi dengan proses-proses itu serta melakukan sinkronisasi di antara proses-proses tersebut (menggunakan signal, atau mekanisme POSIX).

Manajemen proses mengelola pembagian kerja CPU untuk semua thread yang aktif. Kernel menerapkan algoritma penjadwalan yang berjalan dalam jangka waktu konstan berapapun jumlah thread yang minta dilayani. Penjadwalan seperti ini disebut penjadwal O(1) yang berarti bahwa jangka waktu yang sama diperlukan untuk menjadwal satu thread maupun menjadwal banyak thread. Penjadwal O(1) mendukung penggunaan prosesor jamak (multiprocessor) atau biasa disebut prosesor jamak simetris (Symmetric MultiProcessing, SMP). Kode untuk manajemen proses dapat dijumpai dalam direktori ./linux/kernel dan ./linux/arch.

Memory management

Memori dikelola dengan mengelompokkannya ke dalam beberapa "halaman" (page), biasanya setiap halaman berukuran 4KB tergantung arsitektur hardware. Manajemen memori di Linux juga mengelola mekanisme hardware untuk memetakan memori fisik dan virtual.

Sebenarnya manajemen memori lebih dari sekedar mengelola halaman/buffer 4 KB. Linux menyediakan abstraksi di atas buffer 4 KB, misalnya slab allocator. Mekanisme slab allocator menggunakan buffer 4KB sebagai basis namun menempatkan suatu catatan struktur di dalamnya sehingga dapat memberi informasi tentang halaman yang penuh, belum penuh dan kosong. Dengan demikian mekanisme ini dapat membuat alokasi tumbuh lebih besar atau lebih kecil berdasarkan kebutuhan.

Karena mendukung penggunaan berulang dari memori, ada kemungkinan memori yang tersedia menjadi "lelah" (exhausted) artinya terlalu banyak dipakai. Karena itu halaman dapat dipindah dari memori ke disk. Proses ini disebut swapping. Program yang melakukan manajemen memori disimpan di direktori ./linux/mm.

Virtual file system

Sistem berkas maya (virtual file system, VFS) menyediakan abstraksi antarmuka yang seragam untuk berbagai sistem berkas berbeda. VFS menjadi lapisan saklar yang menghubungkan SCI dengan sistem berkas yang didukung oleh kernel (lihat Gambar 2).


Gambar 2. VFS merupakan perantara user dengan sistem berkas

Di atas VFS adalah abstraksi API yang seragam yang berwujud fungsi seperti buka, tutup, baca dan tulis. Di bawah VFS adalah abstraksi sistem berkas yang menentukan bagaimana fungsi-fungsi di atas diimplementasikan. Abstraksi di bagian ini merupakan plug-in untuk sistem berkas yang dipilih (jumlah sistem berkas lebih dari 50). Implementasi sistem berkas terdapat di direktori ./linux/fs.

Di bawah sistem berkas terdapat buffer cache, yang menyediakan beberapa fungsi seragam ke lapisan sistem berkas (yang tidak tergantung sistem berkas yang dipakai). Lapisan cache ini berfungsi mengoptimalkan akses ke piranti fisik dengan menyimpan sementara data (atau membaca data lebih dari yang dibutuhkan sebagai spekulasi kalau-kalau data itu dibutuhkan kemudian). Di bawah buffer cache adalah driver ke piranti yang menerapkan antarmuka untuk piranti fisik yang terpasang.

Network stack

Network stack adalah stack untuk jaringan yang tergantung arsitektur dan mengikuti protokol yang digunakan. Perlu diingat bahwa Internet Protocol (IP) merupakan inti lapisan jaringan yang berada di bawah protokol transport (umumnya yang dipakai adalah Transmission Control Protocol, or TCP). Di atas TCP adalah lapisan soket yang dipanggil di lapisan SCI.

Lapisan soket merupakan API standar pada subsistem jaringan dan menyediakan antarmuka ke berbagai protokol jaringan. Lapisan soket menyediakan cara standar untuk mengelola koneksi jaringan dan mentransfer data antar dua titik. Sedangkan di lapisan transmisi, dapat digunakan protokol PDU (IP Protocol Data Unit), TCP atau UDP (User Datagram Protocol). Kode untuk mengelola jaringan terdapat di direktori ./linux/net.

Device driver

Driver untuk piranti (device driver) merupakan potongan kode program untuk mengakses piranti fisik. Piranti fisik tidak dapat digunakan jika tidak ada drivernya. Mayoritas kode sumber Linux merupakan driver piranti. Linux menyediakan subdirektori khusus untuk driver dan subdirektori ini dibagi lagi menjadi subdirektori berdasar piranti yang didukung, misalnya Bluetooth, I2C, serial, dan lain-lain. Kode sumber piranti ada di direktori ./linux/drivers.

Kode khusus sesuai arsitektur

Kebanyakan kode di kernel Linux tidak tergantung arsitektur. Namun terdapat beberapa unsur yang harus memperhatikan arsitektur untuk kerja normal atau untuk efisiensi. Direktori ./linux/arch menyimpan bagian-bagian kernel yang bergantung arsitektur dan kode-kode ini diwadahi dalam subdirektori sesuai arsitekturnya. Untuk kebanyakan komputer desktop, terdapat subdirektori i386. Setiap subdirektori mengandung subdirektori lagi yang berfokus pada aspek tertentu dari kernel, seperti boot, kernel, memory management, dan lain-lain. Kode khusus sesuai arsitektur dapat ditemui di ./linux/arch.

8.7.08

Sekilas kernel Linux (3): sifat dan fitur

(Bagian 3 dari 4 artikel - ke artikel utama - bagian 4)

Atribut kernel Linux

Pembahasan sistem yang besar dan kompleks akan lebih mudah dipahami jika sistem digambarkan dalam komponen-komponen arsitektural. Demikian ini berlaku pula untuk kernel Linux sebagai sebuah program yang besar.

Kernel Linux mengimplementasikan sejumlah sifat arsitektur yang penting. Pada tingkat tinggi maupun rendah, kernel disusun berlapis menjadi beberapa subsistem yang berbeda. Linux dapat dianggap bersifat monolitik karena Linux memadukan semua pelayanan mendasar (basic service) ke dalam satu kernel. Ini berbeda dengan arsitektur mikrokernel yang meletakkan beberapa pelayanan (service) seperti pelayanan komunikasi, I/O, manajemen proses dan memori, dan beberapa pelayanan spesifik pada lapisan mikrokernel (microkernel layer) yang berbeda. Masing-masing pendekatan arsitektur mempunyai kelebihan, namun perbedaan itu tidak akan dibahas di sini.

Setelah beberapa masa, kernel Linux telah mencapai titik efisiensi dalam hal penggunaan memori dan CPU dan telah menjadi sangat stabil. Namun aspek yang menarik dari Linux, meskipun kode programnya besar dan kompleks, adalah portabel (portability). Artinya Linux dapat dikompail dan jalan pada banyak prosesor dan platform yang masing-masing mempunyai kebutuhan dan kekangan arsitektur (architectural constraint). Satu hal yang juga penting adalah bahwa Linux dapat menjalankan proses dengan unit manajemen memori (memory management unit, MMU) maupun tanpa MMU. Misalnya, uClinux menggunakan kernel Linux tanpa dukungan MMU.

Fitur menarik dari kernel Linux

Kalau portabilitas dan efisiensi masih dianggap kurang, kernel Linux masih memiliki fitur penting yang lain.

Linux, sebagai program open source dan sistem operasi yang dapat diterapkan dalam mesin produksi, merupakan wahana terbaik untuk melakukan ujicoba dan pengembangan protokol baru . Linux mendukung banyak sekali protokol, termasuk TCP/IP, dan mendukung pengembangan jaringan berkecepatan tinggi (kecepatan lebih dari 1 GB Ethernet [GbE] dan 10 GbE). Linux mendukung protokol lain seperti Stream Control Transmission Protocol (SCTP), yang menyediakan fitur canggih di atas TCP (sebagai pengganti protokol tingkat transport).

Linux juga merupakan kernel dinamis yang mendukung penambahan dan pengurangan komponen software dalam keadaan software sedang dijalankan (on the fly). Sifat ini disebut modul kernel yang dapat dimuat secara dinamis (dynamically loadable kernel modules). Modul dapat disisipkan saat booting (misalnya ada piranti yang membutuhkan modul tersebut) atau di sembarang waktu jika diinginkan oleh user.

Perkembangan Linux telah mencapai titik di mana kernel itu dapat digunakan dalam sebuah sistem operasi untuk menjalankan sistem operasi lain (atribut ini disebut hipervisor). Kernel juga telah dimodifikasi menjadi mesin virtual berbasis kernel (Kernel-based Virtual Machine, KVM). Modifikasi ini dapat menjadi antar muka baru pada wilayah user (user space) yang memungkinkan sistem operasi lain dijalankan di atas kernel yang memakai fitur KVM. Di samping menjalankan sistem operasi GNU/Linux lain, Microsoft® Windows® juga dapat divirtualisasi. Satu-satunya kekangan untuk menerapkan fitur ini adalah apakah prosesor mesin dapat menjalankan instruksi dari sistem virtual tersebut (Windows virtual tidak dapat dijalankan di atas GNU/Linux yang berjalan di atas prosesor PowerPC, semata-mata karena Windows tidak mendukung prosesor tersebut).

6.7.08

Sekilas kernel Linux (2): Garis besar

(Bagian 2 dari 4 artikel - ke artikel utama - bagian 3)

Secara garis besar, sistem operasi GNU/Linux dapat dibagi menjadi dua tingkatan, seperti terlihat pada gambar berikut.

Publish Post

Gambar. Arsitektur dasar sistem operasi GNU/Linux

Tingkat pertama adalah wilayah user atau wilayah aplikasi. Di sini aplikasi user dijalankan. Tingkat berikutnya adalah wilayah kernel. Di sini terletak kernel Linux.


Cara memanggil system call interface (SCI)
Dalam prakteknya, arsitektur Linux tidak setegas seperti pada gambar. Misalnya, transisi antara wilayah user dan kernel berbeda-beda tergantung arsitektur. Prosesor x86 yang baru dengan dukungan virtualisasi lebih efisien dalam proses transisi dibanding prosesor x86 lama yang menggunakan perintah INT 80h.
Ada juga yang disebut GNU C Library (glibc), yaitu kumpulan perintah/fungsi yang ditulis dengan bahasa C. Librari ini merupakan antarmuka untuk memanggil sistem (system call interface, SCI) yang melakukan hubungan dengan kernel dan menyediakan mekanisme transisi antara wilayah user dengan kernel. Fungsi terakhir tadi sangat penting karena kernel dan aplikasi user menempati ruang memori yang berbeda dan terproteksi. Perlu diketahui bahwa setiap proses di wilayah user menempati ruang memori virtual masing-masing sedangkan kernel menempati satu ruang memori tertentu.

Kernel dapat dibagi-bagi lagi menjadi tiga tingkat utama. Tingkat paling atas adalah system call interface, yang menjalankan fungsi-fungsi dasar seperti read dan write (proses tulis baca berkas). Tingkatan di bawahnya adalah kode kernel, atau lebih tepatnya adalah kode kernel yang tidak tergantung arsitektur (architecture-independent kernel code). Kode ini sama untuk semua prosesor yang disupport oleh Linux. Tingkatan paling bawah adalah kode kernel yang tergantung arsitektur (architecture-dependent). Kode-kode pada tingkatan ini merupakan paket pendukung hardware (Board Support Package, BSP) yang menyediakan kode yang terkait dengan prosesor atau platform hardware.

4.7.08

Sekilas kernel Linux (1): Sejarah

(Bagian 1 dari 4 artikel - ke bagian 2)

Kernel Linux® adalah inti dari sistem operasi. Sistem operasi mempunyai ukuran yang sangat besar dan kompleks sehingga ditata ke dalam subsistem dan lapisan (layer). Begitu besarnya sistem operasi, bahkan kernel Linux saja mempunyai lebih dari enam juta baris program.


Linux atau GNU/Linux?
Terkadang Linux sebagai sistem operasi diberi sebutan "Linux" saja dan terkadang "GNU/Linux". Mengapa? Linux sebenarnya hanyalah kernel dari sistem operasi. Kernel saja belum cukup untuk digunakan secara fungsional. Diperlukan banyak paket pendukung. Berbagai paket yang menyertai sistem operasi itu kebanyakan merupakan perangkat lunak GNU. Misalnya: window, compiler, shell, perangkat pengembangan program, editor, utiliti, dan lain-lain yang berada di luar kernel. Karena itu GNU/Linux merupakan nama yang lebih tepat untuk sistem operasinya sedangkan Linux merupakan nama kernelnya.

Linux adalah sistem operasi open source yang paling populer, namun ternyata umurnya termasuk muda dibanding sistem operasi lain. Di masa awal komputer, programer membuat program berlandaskan bahasa untuk hardware yang bersangkutan. Tanpa sistem operasi, di suatu waktu hanya satu aplikasi (dan satu orang) yang bisa memakai perangkat keras yang super mahal. Sistem operasi mulai dikembangkan di tahun 1950an untuk lebih menyederhanakan proses pengembangan aplikasi. Contoh sistem operasi di era pertama adalah General Motors Operating System (GMOS) yang dibuat untuk mesin IBM 701 dan FORTRAN Monitor System (FMS) yang dibuat oleh North American Aviation untuk mesin IBM 709.

Pada dasawarsa 1960, Massachusetts Institute of Technology (MIT) bersama beberapa perusahaan mengembangkan sistem operasi bernama Multics (Multiplexed Information and Computing Service) untuk mesin GE-645. Salah satu pihak pengembang, yaitu AT&T, keluar dari proyek Multics dan mengembangkan sistem operasi mereka sendiri di tahun 1970 dan diberi nama Unics. Bahasa pemrograman C kemudian dibuat untuk Unics, sehingga pengembangan sistem operasi menjadi portable.

Dua puluh tahun kemudian, Andrew Tanenbaum membuat versi microkernel dari UNIX® dan diberi nama MINIX (singkatan dari minimal UNIX). MINIX dirancang untuk komputer personal. Sistem operasi inilah yang memberi inspirasi kepada Linus Torvalds memulai pengembangan Linux di awal 1990 (lihat gambar).

Rilis kernel Linux vs jumlah baris program

Linux dengan cepat berevolusi dari karya perseorangan menjadi proyek sedunia yang melibatkan ribuan developer. Ini terjadi karena Linux mengadopsi lisensi model GPL (GNU General Public License). Dengan lisensi GPL, kernel Linux terlindungi dari eksploitasi komersial dan mendapatkan keuntungan dari paket-paket yang dikembangkan oleh proyek GNU (oleh Richard Stallman, jumlah kode GNU jauh lebih kecil dibanding kernel Linux), misalnya paket GCC (GNU Compiler Collection) dan shell.

disadur bebas dengan penyesuaian dari: Anatomy of the Linux kernel