Sabtu, 28 November 2015

FUSE di linux

Filesystem in Userspace (FUSE) merupakan mekanisme sistem operasi untuk sistem operasi Unix-like yang memungkinkan pengguna tidak ber-hak istimewa menciptakan file system mereka sendiri tanpa mengubah kode kernel. Hal ini dicapai dengan menjalankan kode file system di userspace, sedangkan modul FUSE hanya menyediakan "jembatan" untuk antarmuka kernel yang sebenarnya.
Diagram cara kerja FUSE

Module kernel FUSE dan FUSE library berhubungan melalui sebuah special file descriptor yang didapatkan dengan membuka /dev/fuse. FUSE kernal module meneruskan request ke aplikasi fuse anda. aplikasi anda memerintahkan fuse cara menjawab request. FUSE kernal module dan FUSE library berkomunikasi lewat file deskriptor spesial yang diperoleh dengan membuka /dev/fuse. file ini dapat terbuka berkali-kali dan file deskriptor yang diperoleh diteruskan ke mount syscall, untuk menyesuaikan deskriptor dengan filesystem mount.

Installasi FUSE:
  1. Download FUSE dari http://fuse.sourceforge.net/  pada bagian Download stable release
  2. Extract file tar.gz dan masuk ke direktori FUSE. (tar –xvzf fuse-2.9.4.tar.gz)
  3. Lakukan installasi FUSE dengan cara : 
    • Gunakan hak akses super user (sudo su)
    • Ketikkan perintah ./configure
    • Ketikkan perintah make
    • Ketikkan perintah make install
    • FUSE siap digunakan
Membuat file system sendiri menggunakan FUSE :

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/statfs.h>

static const char *dirpath = "/home/[nama user kalian]/[path bebas]";

static int xmp_getattr(const char *path, struct stat *stbuf) {
                int res;
                char fpath[1000];
                sprintf(fpath,"%s%s",dirpath,path);
                res = lstat(fpath, stbuf);
                if(res == -1) return -errno;
                return 0;
}

static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
                char fpath[1000];
                if(strcmp(path,"/") == 0) {
                                path=dirpath;
                                sprintf(fpath,"%s",path);
                }
                else sprintf(fpath, "%s%s",dirpath,path);
                int res = 0;
                DIR *dp;
                struct dirent *de;
                dp = opendir(fpath);
                if(dp==NULL) return -errno;
                while((de = readdir(dp))!=NULL) {
                                res = filler(h, de->d_name, de->d_type);
                                if(res!=0) break;
                }
                closedir(dp);
                return res;
}

static struct fuse_operations xmp_oper = {
                .getattr = xmp_getattr,
                //.readlink = xmp_readlink,
                .getdir = xmp_getdir,
                //.mknod = xmp_mknod,
                //.mkdir = xmp_mkdir,
                //.symlink = xmp_symlink,
                //.unlink = xmp_unlink,
                //.rmdir = xmp_rmdir,
                //.rename = xmp_rename,
                //.link = xmp_link,
                //.chmod = xmp_chmod,
                //.chown = xmp_chown,
                //.truncate = xmp_truncate,
                //.utime = xmp_utime,
                //.open = xmp_open,
                //.read = xmp_read,
                //.write = xmp_write,
                //.release = xmp_release,
                //.fsync = xmp_fsync,
                //.readdir = hello_readdir
};

int main(int argc, char *argv[]) {
                return fuse_main(argc, argv, &xmp_oper);
}

Simpan kemudian compile dengan menggunakan perintah: gcc -Wall [nama file].c `pkg-config fuse --cflags --libs` -o [nama file]
Kemudian buat sebuah direktori, misalnya: /tmp/fuse
Coba jalankan fuse tadi dengan cara: ./[nama file] /tmp/fuse
Maka semua isi direktori /home/[nama user kalian]/[path bebas] akan dimount ke direktori /tmp/fuse

Untuk Fuse ini, kita hanya bermain dalam fungsi - fungsi mana yang akan kita gunakan (cek static struct fuse_operations xmp_oper). Berikut beberapa fungsi dalam fuse :

static int xmp_getattr(const char *path, struct stat *stbuf) {
                int res;
                char fpath[1000];
                sprintf(fpath,"%s%s",dirpath,path);
                res = lstat(fpath, stbuf);
                if(res == -1) return -errno;
                return 0;
}

static int xmp_chmod(const char *path, mode_t mode) {
               int res;
               char fpath[1000];
               char direktori[] = "/home/[nama user kalian]/[path bebas]";
               sprintf(fpath,"%s%s", direktori, path);
               res = chmod(fpath, mode);
               if(res == -1) return -errno;
               return 0;
}


static int xmp_chown(const char *path, uid_t uid, gid_t gid) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              res = lchown(fpath, uid, gid);
              if(res == -1) return -errno;
              return 0;
}

static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
              char fpath[1000];
              if(strcmp(path,"/") == 0) {
                            path=dirpath;
                            sprintf(fpath,"%s",path);
              }
              else sprintf(fpath, "%s%s",dirpath,path);
              int res = 0;
              DIR *dp;
              struct dirent *de;
              dp = opendir(fpath);
              if(dp==NULL) return -errno;
              while((de = readdir(dp))!=NULL) {
                            res = filler(h, de->d_name, de->d_type);
                            if(res!=0) break;
              }
              closedir(dp);
              return res;
}

static int xmp_mkdir(const char *path,mode_t mode) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s",dirpath,path);
              res = mkdir (fpath,mode);
              if(res == -1)
              return -errno;
              return 0;
}

static int xmp_symlink(const char *from, const char *to) {
              int res;
              char ffrom[1000];
              char fto[1000];
              sprintf(ffrom,"%s%s",dirpath,from);
              sprintf(fto,"%s%s",dirpath,to);
              res = symlink(ffrom, fto);
              if(res == -1) return -errno;
              return 0;
}

static int xmp_link(const char *from, const char *to) {
              int res;
              char ffrom[1000];
              char fto[1000];
              sprintf(ffrom,"%s%s",dirpath,from);
              sprintf(fto,"%s%s",dirpath,to);
              res = link(ffrom, fto);
              if(res == -1)
              return -errno;
              return 0;
}

static int xmp_unlink(const char *path) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              res = unlink(fpath);
              if(res == -1) return -errno;
              return 0;
}

static int xmp_truncate(const char *path, off_t size) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              res = truncate(fpath, size);
              if(res == -1) return -errno;
              return 0;
}

static int xmp_utime(const char *path, struct utimbuf *buf) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              res = utime(fpath, buf);
              if(res == -1) return -errno;
              return 0;
}

static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              res = mknod(fpath, mode, rdev);
              if(res == -1)
              return -errno;
              return 0;
}

static int xmp_open(const char *path, int flags) {
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              if(strcmp(fpath,"/home/[nama user kalian]")==0) {
                          system("zenity --error --text=\"An error occurred!\" --title=\"Warning!\"");
                            res = open(fpath, flags);
                            if(res == -1)
                            return -errno;
                            close(res);
              }
              return 0;
}

static int xmp_read(const char *path, char *buf, size_t size, off_t offset) {
              int fd;
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              fd = open(fpath, O_RDONLY);
              if(fd == -1) return -errno;
              res = pread(fd, buf, size, offset);
              if(res == -1) res = -errno;
              close(fd);
              return res;
}

static int xmp_write(const char *path, const char *buf, size_t size,off_t offset) {
              int fd;
              int res;
              char fpath[1000];
              sprintf(fpath,"%s%s", dirpath, path);
              fd = open(fpath, O_WRONLY);
              if(fd == -1) return -errno;
              res = pwrite(fd, buf, size, offset);
              if(res == -1) res = -errno;
              close(fd);
              return res;
}

static int xmp_rename(const char *from, const char *to) {
              int res;
              char ffrom[1000];
              char fto[1000];
              system("mkdir /home/[nama user kalian]/[path bebas]");
              system("chmod 777 [path bebas]");
              char direktori[] = "/home/[nama user kalian]/[path bebas]";
              sprintf(ffrom,"%s%s",dirpath,from);
              sprintf(fto,"%s%s",direktori,to);
              res = rename(ffrom, fto);
              if(res == -1) return -errno;
              return 0;
}

Jumat, 06 November 2015

Thread dan IPC

Thread adalah bagian terkecil dari suatu proses yang bisa dijadwalkan oleh sistem operasi.
Thread dibagi menjadi 2, yaitu :

  1. Single Threading, proses yang berjalan hanya memiliki 1 thread yang berjalan
  2. Multi Threading, proses yang berjalan memiliki lebih dari 1 thread (berjalan secara bersamaan)

Misalkan kita ingin menggunakan thread dimana kita dapat memutar 2 lagu secara bersama - sama.
Contoh Program :

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid[2];
char lagu1[20],lagu2[20],tmp[50];

void* play(void *args) {
pthread_t id=pthread_self();
if(pthread_equal(id,tid[0])) {
snprintf(tmp, sizeof(tmp), "cvlc %s.mp3", lagu1);
system(tmp);
}
else if(pthread_equal(id,tid[1])) {
snprintf(tmp, sizeof(tmp), "cvlc %s.mp3", lagu2);
system(tmp);
}
return NULL;
}

int main(void) {
int err,i=0;

printf("\nMasukkan judul lagu pertama : ");
scanf("%s",lagu1);

printf("\nMasukkan judul lagu kedua : ");
scanf("%s",lagu2);

while(i<2) {
err=pthread_create(&(tid[i]),NULL,&play,NULL);
if(err!=0) printf("\ncan't create thread : [%s]",strerror(err));
else i++;
}

pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);

return 0;
}

IPC (Interprocess Communication) adalah mekanisme pertukaran data antara satu proses dengan proses lainnya, baik dalam komputer yang sama atau komputer yang jauh (terhubung melalui jaringan).
Beberapa contoh IPC :

  1. Pipes
  2. Message Queue
  3. Shared Memory
  4. Socket

Misalkan kita ingin menggunakan pipes dimana kita berkirim pesan dari terminal 1 ke terminal lainnya.

Program 1 (pengirim) :

#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>

int main() {
int fd;
char *myfifo = "/tmp/myfifo";

mkfifo(myfifo,0666);

fd = open(myfifo, O_WRONLY);
write(fd, "Gede Wayan Dharmawan",sizeof("Gede Wayan Dharmawan"));
close(fd);

unlink(myfifo);

return 0;
}

Program 2 (penerima) :

#include<fcntl.h> #include<stdio.h> #include<sys/stat.h> #include<unistd.h> #define MAX_BUF 1024 int main() { int fd; char *myfifo = "/tmp/myfifo"; char buf[MAX_BUF]; fd = open(myfifo, O_RDONLY); read(fd,buf,MAX_BUF); printf("Isi Pesan : %s\n",buf); close(fd); return 0; }

Minggu, 18 Oktober 2015

Daemon

Daemon adalah proses yang berjalan di balik layar (background) dan tidak berinteraksi langsung dengan user melalui standard input/output

Pembuatan Daemon :

Fork Parent Process dan penghentian Parent Process
Langkah pertama adalah melakukan forking untuk membuat process baru kemudian mematikan Parent Process. Process induk yang mati akan membuat system mengira proses telah selesai sehingga akan kembali ke terminal user. Proses anak yang melanjutkan program setelah proses induk dimatikan.


Mengubah mode file menggunakan UMASK(0);
Untuk menulis  beberapa file (termasuk logs) yang dibuat oleh daemon, mode file harus diubah untuk memastikan bahwa file tersebut dapat ditulis dan dibaca secara benar. Pengubahan mode file menggunakan implementasi umask().

Membuat Unique Session ID (SID)
Child Process harus memiliki unik SID dari kernel untuk dapat beroperasi. Sebaliknya, Child process menjadi Orphan Proses pada system. Tipe pid_t yang dideklarasikan pada bagian sebelumnya, juga digunakan untuk membuat SID baru untuk child process. Pembuatan SID baru menggunakan implementasi setsid(). Fungsi setsid() memiliki return tipe yang sama seperti fork(). 




Mengubah Directory Kerja
Directori kerja yang aktif harus diubah ke suatu tempat yang telah pasti akan selalu ada. Pengubahan tempat direktori kerja dapat dilakukan dengan implementasi fungsi chdir (). Fungsi chdir() mengembalikan nilai -1 jika gagal.


Menutup File Descriptor Standar
Salah satu dari langkah terakhir dalam mengeset daemon adalah menutup file descriptor standar (STDIN, STDOUT, STDERR). Karena daemon tidak perlu menggunakan kendali terminal, file descriptor dapat berulang dan berpotensi memiliki bahaya dalam hal keamanan. Untuk mengatasi hal tersebut maka digunakan implemtasi fungsi close().


Membuat Loop utama (inti kerja dari daemon)
Daemon bekerja dalam jangka waktu tertentu, sehingga diperlukan sebuah looping.



Jumat, 25 September 2015

Sistem Operasi khususnya Linux

Sebelum kita membahas Linux, kita bahas dulu tentang "Sistem Operasi".

Sistem Operasi adalah Perangkat lunak yang mengelola perangkat keras dan menyediakan layanan umum / sumber daya untuk program komputer.

Komponen maajemen utama pada sistem operasi :
  1. Manajemen Proses
  2. Manajemen Memori
  3. Manajemen Sistem Berkas
  4. Manajemen Input/Output
1) Manajemen Proses
           Proses adalah sebuah program yang sedang dieksekusi. Sebuah proses membutuhkan beberapa sumber daya untuk menyelesaikan tugasnya. Sumber daya tersebut dapat berupa CPU time, memori, berkas-berkas, dan perangkat-perangkat masukan/ keluaran. Sistem operasi mengalokasikan sumber daya-sumber daya tersebut saat proses itu diciptakan atau sedang diproses / dijalankan. Ketika proses tersebut berhenti dijalankan, sistem operasi akan mendapatkan kembali semua sumber daya yang bisa
digunakan kembali.

2) Manajemen Memori Utama
            Memori utama atau lebih dikenal sebagai memori adalah sebuah array  yang besar dari word atau byte, yang ukurannya mencapai ratusan, ribuan, atau bahkan jutaan. Setiap word  atau byte mempunyai alamat tersendiri. Memori utama berfungsi sebagai tempat penyimpanan instruksi / data yang akses datanya digunakan oleh CPU dan perangkat masukan / keluaran. Memori utama termasuk tempat penyimpanan data yang yang bersifat volatile (tidak permanen)  yaitu data akan hilang kalau komputer dimatikan.

3) Manajemen Berkas
            Berkas adalah kumpulan informasi yang berhubungan, sesuai dengan tujuan pembuat berkas tersebut. Umumnya berkas merepresentasikan program dan data. Berkas dapat mempunyai struktur yang bersifat hirarkis (direktori, volume, dll.). Sistem operasi mengimplementasikan konsep abstrak dari berkas dengan mengatur media penyimpanan massa, misalnya tapes dan disk.

4) Manajemen Sistem Masukan / Keluaran
         Sering disebut device manager. Menyediakan device driver yang umum sehingga operasi masukan/ keluaran dapat seragam (membuka, membaca, menulis, menutup). Contoh: pengguna menggunakan operasi yang sama untuk membaca berkas pada perangkat keras, CD-ROM dan floppy disk.

Layanan yang Disediakan Sistem Operasi :
  1. Program development
  2. Editors and debuggers
  3. Program execution
  4. OS handles scheduling of numerous tasks required to execute a program
  5. Access I/O devices
  6. Each device will have unique interface
  7. OS presents standard interface to users
  8. Controlled access to files
  9. Accessing different media but presenting a common interface to users
  10. Provides protection in multi-access systems
  11. System access
  12. Controls access to the system and its resources
  13. Error detection and response
  14. Internal and external hardware errors
  15. Software errors
  16. Operating system cannot grant request of application
  17. Accounting
  18. Collect usage statistics
  19. Monitor performance
Linux adalah salah satu jenis sistem operasi, dimana sistem operasi linux ini bersifat Open Source.

Bash Command Line pada Linux :
  1. ls digunakan untuk memberikan informasi daftar tentang file
  2. pwd digunakan untuk memberitahu letak direktory saat ini (direktory kerja)
  3. mkdir digunakan untukmembuat folder baru
  4. chmod digunakan untuk mengubah izin akses file atau direktory
  5. chown digunakan untukmengubah kepemilikan file (user atau grup)
  6. chroot digunakan untukmengubah direktory root
  7. sudo digunakan untuk mengganti identitas user
  8. grep digunakan untuk mencari file dengan pola tertentu
  9. ps digunakan untuk menampilkan status proses
  10. halt digunakan untuk menghentikan atau restart sistem operasi
  11. cd digunakan untuk pindah ke direktory tertentu
  12. rm digunakan untuk menghapus file
  13. mv digunakan untuk memindahkan atau mengubah nama file atau direktory
  14. date digunakan untuk menampilkan atau mengubah waktu (tanggal, bulan, tahun, jam, menit, detik)
  15. free digunakan untuk menampilkan memori yang digunakan
  16. dan lain lain
Contoh Soal Problem Solving :

Cayza diberi tugas oleh dosennya untuk merubah codingan program bilangan prima dari bahasa C ke bash script.
Input : baris pertama berisi bilangan n
Output : semua bilangan prima <= n
Contoh :
     5
     2 3 5

     10
     2 3 5 7
Bantulah Cayza untuk menyelesaikan tugasnya ini !

Konsep : semua bilangan prima pasti hanya memiliki 2 faktor yaitu 1 dan dirinya dia sendiri

Logika : karena faktor dari bilangan prima pasti 1 dan dirinya dia sendiri, maka jika ada bilangan lain : (1 < a < n | n%a=0), maka n bukanlah bilangan prima (n,a adalah bilangan asli)

Kodingan :

#!/bin/bash
input=$1
for i in `seq 1 $input`;
do
    faktor=0
    for j in `seq 2 $i`;
    do
        if [ $(($i%$j)) -eq 0 ]
        then let faktor=$faktor+1;
        fi
        if [ $faktor -eq 2 ]
        then break
        fi
    done
    if [ $faktor -eq 1 ]
    then printf '$i '
    fi
done
echo

Penjelasan :
 #!/bin/bash
merupakan default header karena kita menggunakan bash scripting

input=$1
merupakan cara kita menerima inputan. bilangan yang diinputkan akan otomatis disimpan dalam variable input

for i in `seq 1 $input`;
merupakan bentuk perulangan dimulai dari 1 sampai angka inputan

faktor=0
merupakan variable yang digunakan untuk menampung ada berapakah bilangan i memiliki faktor
 
for j in `seq j $i`;
merupakan bentuk perulangan yang akan digunakan untuk mencari faktor dari i

if [ $(($i%$j)) -eq 0 ]
then let faktor=$faktor+1;
fi 
merupakan cara penggunaan if dimana kita membandingkan 2 variable yaitu i dan j (apakah i habis dibagi j), ini berguna untuk mencari apakah j faktor dari i. jika ya, maka variabel faktor akan bertambah sebanyak 1

if [ $faktor -eq 2 ]
then break
fi
karena bilangan prima hanya memiliki 2 faktor maka jika ditemukan faktor lain selain dirinya dia sendiri maka bilangan itu bukanlah bilangan prima (bilangan prima saat variable faktor bernilai 1, karena kita menggunakan j dari 2,bukan 1)
untuk mengurangi waktu perhitungan, jika faktor telah lebih dari 1 (bernilai 2) maka pengecekan dihentikan
 
if [ $faktor -eq 1 ]
then printf '$i '
fi
digunakan untuk menampilkan bilangan yang memiliki syarat variabel faktor bernilai 1 saat bilangan itu dicek

Terimakasih atas kesediaannya membaca tulisan ini, jika ada kesalahan saya mohon maaf.
:) :) :) :) :)