Skip navigation


Melanjutkan postingan tentang modul kernel yang dulu.

Biasanya untuk melakukan pemindahan data antara dua buah program cukup dengan menggunakan sebuah file yang dibaca bersama (selain dengan menggunakan IPC). Hal ini cukup sulit untuk dilaksanakan pada modul kernel karena pada dasarnya modul tidak disediakan fungsi file I/O layaknya system call open(). Menulis file pada kernel space menjadi cukup sulit.

Salah satu cara yang mudah melakukan komunikasi antara sebuah kernel module dan user space program adalah dengan menggunakan procfs. Procfs adalah sebuah filesystem yang menyediakan informasi mengenai process-process dalam kernel. Procfs ini dapat dibuka di folder /proc.

$cd /proc
$ls -l | less
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 1
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 119
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 120
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 121
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 1369
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 1372
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 1385
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 1392
dr-xr-xr-x  6 root       root               0 2009-01-07 15:07 2

Di sana tersimpan data-data mengenai process yang sedang dijalankan. Folder-folder yang memiliki nama berupa angka merepresentasikan process dengan process ID (PID) yang  sama dengan nama folder tersebut. Di dalam folder tersebut tersimpan data-data mengenai process yang bersangkutan.

Procfs ini dapat digunakan karena dapat dibaca baik oleh modul kernel maupun user space program. Selain itu terdapat fungsi yang dapat digunakan untuk membuat, menghapus, membaca, dan menulis sebuah file pada procfs.

Sekarang untuk kodenya, kita kembangkan kode yang kemarin.

#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL v2");

static int __init init(void)
{
  printk(KERN_INFO "Module start!\n");
  return 0;
}

static int __exit fini(void)
{
  printk(KERN_INFO "Module finish!\n");
  return 0;
}

module_init(init);
module_exit(fini);

Untuk membuat sebuah procfs diberikan sebuah fungsi yakni create_proc_entry(). Kodenya

#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define PROCFS_MAX_SIZE 1024
#define PROCFS_NAME "contoh"

MODULE_LICENSE("GPL v2");

struct proc_dir_entry * proc_file;

static int __init init(void)
{
  printk(KERN_INFO "Module start!\n");
  proc_file = create_proc_entry(PROCFS_NAME, 0644, NULL);
  if (proc_file == NULL) {
		remove_proc_entry(PROCFS_NAME, &proc_root);
		printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
		        PROCFS_NAME);
		return -ENOMEM;
  }
  proc_file->owner      =  THIS_MODULE;
  proc_file->mode       =  S_IFREG | S_IRUGO;
  printk(KERN_INFO "ProcFS file /proc/%s created\n", PROCFS_NAME);
  return 0;
}

static int __exit fini(void)
{
  remove_proc_entry(PROCFS_NAME, &proc_root);
  printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME);
  printk(KERN_INFO "Module finish!\n");
  return 0;
}

module_init(init);
module_exit(fini);

Kalau modul di atas dijalankan maka akan dibuat sebuah file bernama contoh pada direktori /proc

#insmod contoh.ko
#ls /proc | grep contoh
contoh
#rmmod contoh
#ls /proc | grep contoh
#dmesg | tail -n 4
[ 2009.577439] Module start!
[ 2009.577535] ProcFS file /proc/contoh created
[ 2014.466464] /proc/contoh removed
[ 2014.466594] Module finish!
#

Setelah modul dihapus maka file tersebut akan hilang.

Untuk menulis dan membaca file tersebut, kita dapat memberikan spesifikasi sebuah fungsi dengan parameter yang sudah ditentukan.

/* Untuk menulis */
int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data)
/* Untuk membaca */
int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data)

Kedua fungsi itu nantinya akan seperti sebuah trigger. Fungsi procfile_read() akan dijalankan jika file dibaca oleh user space program, sebaliknya fungsi procfile_write() dijalankan.

Kodenya menjadi

#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define PROCFS_MAX_SIZE 1024
#define PROCFS_NAME "contoh"

MODULE_LICENSE("GPL v2");

/* */
struct proc_dir_entry * proc_file;
/* Buffer */
static char procfs_buffer[PROCFS_MAX_SIZE];
/* Buffer size */
static unsigned long procfs_buffer_size = 0;

int procfile_read(char *buffer,
              char **buffer_location,
              off_t offset, int buffer_length, int *eof, void *data)
{
        int ret;
	printk(KERN_INFO "Writing data to user\n");
        if (offset > 0) {
        	/* we have finished to read, return 0 */
        	ret = 0;
	} else {
        	/* string output disimpan pada string buffer */
		ret = sprintf(buffer, "Hello World!\n");
	}
	return ret;
}

int procfile_write(struct file *file, const char *buffer, unsigned long count,
                   void *data)
{
	printk(KERN_INFO "Receiving data from user\n");
        /* get buffer size */
        procfs_buffer_size = count;
        if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
                procfs_buffer_size = PROCFS_MAX_SIZE;
        }
        /* write data to the buffer */
        if (copy_from_user(procfs_buffer, buffer, procfs_buffer_size)) {

		return -EFAULT;
        }
        /* bersiap-siap parsing */
        int buff_size;
        buff_size = procfs_buffer_size;
        if (buff_size == 0)
        {
        	/* tidak ada yang mau diparsing */
        }
        else
        {
        	/* parsing */
        	char * buffz = buffer;
        	/* string input disimpan di buffz */
		printk(buffz);
        }
        return procfs_buffer_size;
}

static int __init init(void)
{
  printk(KERN_INFO "Module start!\n");
  /* Membuat entry pada procfs */
  proc_file = create_proc_entry(PROCFS_NAME, 0644, NULL);
  if (proc_file == NULL) {
		remove_proc_entry(PROCFS_NAME, &proc_root);
		printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
		        PROCFS_NAME);
		return -ENOMEM;
  }
  proc_file->read_proc  =  procfile_read;
  proc_file->write_proc =  procfile_write;
  proc_file->owner      =  THIS_MODULE;
  proc_file->mode       =  S_IFREG | S_IRUGO;
  proc_file->uid        =  0;
  proc_file->gid        =  0;
  proc_file->size       =  37;
  printk(KERN_INFO "ProcFS file /proc/%s created\n", PROCFS_NAME);
  return 0;
}

static int __exit fini(void)
{
  /* Menghapus entry pada procfs */
  remove_proc_entry(PROCFS_NAME, &proc_root);
  printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME);
  printk(KERN_INFO "Module finish!\n");
  return 0;
}

module_init(init);
module_exit(fini);

Kedua baris

  proc_file->read_proc  =  procfile_read;
  proc_file->write_proc =  procfile_write;

dimaksudkan untuk mengassign fungsi yang akan dijalankan saat proc_file dibaca atau ditulis oleh program lain. Fungsi pertama bertugas untuk menampilkan “Hello World!” ketika file dibaca program lain, fungsi kedua bertugas untuk menampilkan string yang ditulis oleh program lain.

Hasilnya

#insmod contoh.ko
#cat /proc/contoh
Hello World!
#rmmod contoh
#insmod contoh.ko
#cat >> /proc/contoh
testestes

#rmmod contoh
#dmesg | tail -n 6
[ 3081.346050] Module start!
[ 3081.346150] ProcFS file /proc/contoh created
[ 3094.551650] Receiving data from user
[ 3094.551766] testestes
[ 3107.989225] /proc/contoh removed
[ 3107.989303] Module finish!

Penggunaan handler tersebut dapat dicek dengan menggunakan perintah cat. Tapi system call untuk file I/O (open(), close(), write(), read()) dapat digunakan pada program yang akan berkomunikasi dengan kernel module.

File kode dapat diunduh di sini (jangan lupa direname ke *.zip)

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: