Sabtu, 28 November 2015

FUSE Bukan Penggabungan

Belajar Sistem Operasi #4

FUSE (Filesystem in UserSpacE)

Apa itu FUSE?
Sebuah mekanisme di sistem operasi Unix yang memungkinkan pengguna tidak ber-hak istimewa menciptakan file system mereka sendiri tanpa mengubah kode kernel dengan menjalankan kode file system di userpace, sedangkan modul FUSE hanya untuk menjembatani antarmuka kernel. Singkat cerita, FUSE ini seperti kita misalnya membuka file /home tapi di sebuah direktori berbeda.

Cara membuat FUSE
Untuk membuat FUSE kita harus menginstall modul FUSE terlebih dahulu.
Berikut langkah langkahnya :
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 :
    a. Gunakan hak akses super user (sudo su)
    b. Ketikkan perintah ./configure
    c. Ketikkan perintah make
    d. Ketikkan perintah make install
4. FUSE siap digunakan

Setelah kita sudah menginstall FUSE, barulah kita membuat modul FUSEnya:

#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/satria/Documents";

char address[1000];

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)
{
    DIR *dp;
    struct dirent *de;
    int res = 0;
    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    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_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_chmod(const char *path, mode_t mode)
{
    int res;

    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    res = chmod(fpath, mode);
    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);
    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);
    strcpy(address,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)                                                                //saat write file
{
    int fd;
    int res;
    int res1;
    char fpath[1000],temp1[1000];

    sprintf(fpath, "%s%s", dirpath, path);
    fd = open(fpath, O_WRONLY);
 
    sprintf(temp1, "%s%s", dirpath, address);
    res1 = chmod(temp1, 0000);
    if(res1 == -1)
        res1 = -errno;

    if(fd == -1)
        return -errno;

    res = pwrite(fd, buf, size, offset);
    if(res == -1)
        res = -errno;

    close(fd);
    return res;
}

static struct fuse_operations xmp_oper = {
.getattr = xmp_getattr,
.getdir = xmp_getdir,
.mknod = xmp_mknod,
.chmod = xmp_chmod,
.open = xmp_open,
.read = xmp_read,
.write = xmp_write,

};

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

Seperti itu kodingan FUSE nya, untuk modul dan dokumentasi lainnya bisa diliat di internet tentang dokumentasi FUSE.
Pada kodingan diatas, modul FUSE yang dibuat adalah untuk mengunci file yang sudah pernah dikopi.

Modifikasi dan Menjalankan FUSE
  • Ganti bagian static const char *dirpath = "/home/satria/Documents" dengan static const char *dirpath = "/home/[nama user kalian]/Documents"
  • 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]/Downloads akan dimount ke direktori /tmp/fuse
  • Coba masuk ke /tmp/fuse dan jalankan perintah ls, maka semua isi direktori tersebut akan ditampilkan. Dan jika file dikopi maka file tersebut dikunci.
 Sekian belajar sisop kita kali ini. Semoga bermanfaat #FUSE

Jumat, 06 November 2015

Thread dan IPC

Belajar Sistem Operasi #3

Perkenalan Thread dan IPC
  1. Thread adalah bagian kecil dari suatu proses yang bisa di jadwalkan oleh sistem operasi. Thread juga disebut sebagai proses ringan (lightweight).
    • Single Threading : Adalah sebuah proses yang hanya memiliki satu thread yang berjalan. Biasanya fungsi thread ini digunakan sebagai pengendali jalannya proses.
    • Multi Threading : Adalah proses yang memiliki lebih dari satu thread yang berjalan didalamnya,sehingga dalam hal ini proses dapat menjalankan lebih dari satu tugas dalam satu waktu.
  2. Interprocess Communication (IPC) adalah cara atau mekanisme pertukaran data antara satu proses dengan proses lainnya, baik itu proses yang berada di dalam komputer yang sama, atau komputer jarak jauh yang terhubung melalui jaringan.
    • Pipe : Pipe merupakan komunikasi sequensial antar proses yang saling terelasi, namun pipe memiliki kelemahan yaitu hanya bisa digunakan untuk komunikasi antar proses yang saling berhubungan, dan komunikasinya yang dilakukan adalah secara sequensial.
    • Message Queue : Sistem berkirim pesan adalah proses komunikasi antar bagian sistem untuk membagi variabel yang dibutuhkan. Proses ini menyediakan dua operasi yaitu mengirim pesan dan menerima pesan.
    • Shared Memory  : Sistem Berbagi Memori merupakan salah satu cara komunikasi antar proses dengan cara mengalokasikan suatu alamat memori untuk dipakai berkomunikasi antar proses. Alamat dan besar alokasi memori yang digunakan biasanya ditentukan oleh pembuat program. Pada metode ini, sistem akan mengatur proses mana yang akan memakai memori pada waktu tertentu sehingga pekerjaan dapat dilakukan secara efektif.
    • Socket : Bentuk dari komunikasi yaitu UDP dan TCP menggunakan abstraksi socket yang menyediakan endpoint untuk komunikasi antar proses. Socket bisa dijalankan di berbagai platform(BSD UNIIX, UNIX, Linux, Windows, & Machintos OS).
Contoh Implementasi Thread

Fatih adalah seorang network administrator, dia bekerja menggunakan linux server. Suatu ketika fatih merasa jenuh dengan pekerjaannya dia ingin mendengarkan lagu, tetapi linux server tidak memiliki GUI sehingga fatih harus memutar musik menggunakan konsol/terminal. Bantulah fatih membuat pemutar musik berbasis konsol.
Pemutar musik memiliki spesifikasi sebagai berikut :
1. Perintah help untuk menampilkan daftar perintah yang dapat digunakan.
2. Memiliki fitur list untuk menampilkan semua lagu pada folder playlist
3. Memiliki fitur play untuk menjalankan lagu
4. Memiliki fitur pause setelah t detik
5. Memiliki fitur continue setelah t detik
6. Memiliki fitur stop setelah t detik

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


pthread_t tid[10];
int n;

void* playandcount(void *arg){
 unsigned long i=0;
 pthread_t id=pthread_self();
 int iter;
 if(pthread_equal(id,tid[1])){
  system("clear");
  printf("\nHelp List\n");
   printf("Press the below number to execute command\n");
   printf("1===Show Help command\n");   
   printf("2===Show playlist\n");
   printf("3===Play\n");
   printf("4===Pause after x sec\n");
   printf("5===Continue after x sec\n");
   printf("6===Stop after x sec\n");
 }
 else if(pthread_equal(id,tid[2])){
  system("clear");
  system("ls | grep .mp3");
 } 
 else if(pthread_equal(id,tid[3])){
  system("clear");
  system("mpg123 Try.mp3");
 }
 else if(pthread_equal(id, tid[4])){
  system("clear");  
  sleep(n);
  system("pkill -STOP mpg123");
 }
 else if(pthread_equal(id, tid[5])){
  system("clear");
  sleep(n);
  system("pkill -CONT mpg123");
 }
 else if(pthread_equal(id,tid[6])){
  system("clear");
  sleep(n);
  system("pkill mpg123");
 }
 return NULL;
}

int main(void){
  system("clear");
  while(1){
   int flag=0;
   int comm;   
   int i=0;
   int err=0;
   scanf("%d", &comm);
   if(comm==4 || comm==5 || comm==6)
    scanf("%d", &n);
   printf("\n\n");
  
    if (err!=0)
     printf("\ncan't create thread : [%s]", strerror(err));
    else{
     err=pthread_create(&(tid[comm]), NULL, &playandcount, NULL);
    }
   
  } 
 return 0;
}


Contoh Implementasi IPC (Pipe)

Raja Takeshi memiliki sebuah tantangan keren bagi orang-orang yang ingin masuk ke istananya. Tantangan ini disebut “Lubang Setan”. Tantangan ini memiliki aturan sebagai berikut: 
- Masing-masing pemain (Raja Takeshi dan si penantang) memiliki 16 lubang yang nantinya bisa diisi ranjau.
- Takeshi dan si penantang masing-masing memiliki 16 buah ranjau yang bisa dipakai serta poin
awal 0.
- Selama pertandingan, Takeshi dan penantang akan saling bergantian mengisi lubang-lubang tersebut dengan ranjau sedangkan salah satunya memberikan tebakan lubang mana saja yang aman dari ranjau.
- Setiap gilirannya, pemain bisa memasang 0 - 4 ranjau di lubang yang berbeda, dan lawannya menebak 4 lubang.
- Pemain yang menebak mendapatkan poin dari jumlah tebakan yang tidak terkena ranjau, sedangkan pemain yang memasang ranjau mendapat poin dari jumlah ranjau yang memakan korban.
- Cara pemasangan maupun penebakan ranjau adalah dengan menginputkan angka-angka yang menunjukkan nomor lubang.

CODE
Player 1:
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(){
 int fd,fs,fsc,ffe1,ffe2;
 int fc,ranjau[5],tebak[4];
 int entry[16];
 int counterentry=0,counterentry2=0;;
 int flagentry=0;
 int flagentry2=0;

 char *fifo1 = "/tmp/fifo1";
 char *fifo2="/tmp/fifo2";
 char *fifoscore="/tmp/fifoscore";
 
 int flag;
 mkfifo(fifo1,0666);
 mkfifo(fifoscore,0666);
 fd = open(fifo1, O_WRONLY);
 fs = open(fifo2,O_RDONLY);
 fsc = open(fifoscore,O_RDWR);
 int i,j,counter=0;
 int scorePlayer[3];
 
 scorePlayer[1]=0;
 scorePlayer[2]=0;

 while(counterentry+counterentry2<32){
 if(counterentry<16){
 system("clear");
 for(i=0;i<4;i++)
 {
  ranjau[i]=0;
 }

 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);
 //BOM
 for(i=0;i<4;i++)
 {
 
  printf("Bom ke-%d : ",i+1);
  scanf("%d",&ranjau[i]);
  while(ranjau[i]<0 || ranjau[i]>16) 
  { 
   printf("Lubang tersebut tidak tersedia\n");
   printf("Bom ke-%d : ",i+1);
   scanf("%d",&ranjau[i]);
  }
  for(j=0;j<counterentry;j++)
  {
   while(ranjau[i]==entry[j])
   {
    if(ranjau[i]==0) break;
    printf("Anda telah memasukkan ranjau ke lubang tersebut\n");
    printf("Bom ke-%d : ",i+1);
    scanf("%d",&ranjau[i]);
   }
  }
  if(ranjau[i]!=0) 
  {
   entry[counterentry]=ranjau[i];
   counterentry++;
  }
  if(counterentry>=16) break; 
 }  
 }

 ranjau[4]=counterentry;
 write(fd,ranjau,sizeof(ranjau)); 
 if(counterentry+counterentry2>=32) break;
 
 system("clear");
 
 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);

 //TEBAK
 read(fsc,scorePlayer,sizeof(scorePlayer));
 read(fs, ranjau, sizeof(ranjau));
 counterentry2=ranjau[4];
 system("clear");
 
 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);
 
 for(i=0;i<4;i++)
 {
  printf("Tebak bom ke-%d : ",i+1);
  scanf("%d",&tebak[i]);
  while(tebak[i]<=0 || tebak[i]>16) 
  { printf("Lubang tersebut tidak tersedia\n");
   printf("Tebak bom ke-%d : ",i+1);
   scanf("%d",&tebak[i]);
  }
  for(j=0;j<i;j++)
  {
   while(tebak[i]==tebak[j])
   {
    printf("Anda telah menebak lubang tersebut\n");
    printf("Tebak bom ke-%d : ",i+1);
    scanf("%d",&tebak[i]);
   }
  }
 }
 

 //HITUNG
 for(j=0;j<4;j++){
  flag=0;
  for(i=0;i<4;i++)
  { 
   if(ranjau[j]==tebak[i]) flag=1;
   if(ranjau[j]==0) flag=2;
  }
  if(flag==1) scorePlayer[1]=scorePlayer[1]+1;
  else if(flag==0) scorePlayer[2]=scorePlayer[2]+1;
 }
 write(fsc,scorePlayer,sizeof(scorePlayer));
 
 if(counterentry+counterentry2>=32) break;
 }
 
 system("clear");
 
 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);

 if(scorePlayer[1]>scorePlayer[2]) 
 printf("*** PLAYER 1 WINS ***");
 else if(scorePlayer[1]==scorePlayer[2])
 printf("*** ITS A DRAW ***");
 else 
 printf("*** PLAYER 2 WINS ***");
 close (fd);
 close (fc);
 close (fs);
 unlink(fifo1);
 
 return 0;
} 
 

Player 2 :
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(){
 int fd,fc,fs,fsc,ffe1,ffe2;
 char *fifo1 = "/tmp/fifo1";
 char *fifo2="/tmp/fifo2";
 char *fifoscore="/tmp/fifoscore";

 int entry[16];
 int counterentry=0,flagentry=0;
 int flagentry2=0;
 int counterentry2=0;
 mkfifo(fifo2,0666);
 mkfifo(fifoscore,0666);
 
 int ranjau[5];
 int tebak[4];
 int i,j;
 int scorePlayer[3];
 int counterplayer2=0;
 int flag=0;
 scorePlayer[1]=0;
 scorePlayer[2]=0;

 fd = open(fifo1, O_RDONLY);
 fs = open(fifo2,O_WRONLY);
 fsc = open(fifoscore,O_RDWR);

 while(counterentry+counterentry2<32){
 
 system("clear");
 
 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);
 //TEBAK
 read(fd, ranjau, sizeof(ranjau));
 counterentry2=ranjau[4];

 for(i=0;i<4;i++)
 {
  printf("Tebak bom ke-%d : ",i+1);
  scanf("%d",&tebak[i]);
  while(tebak[i]<=0 || tebak[i]>16) 
  { printf("Lubang tersebut tidak tersedia\n");
   printf("Tebak bom ke-%d : ",i+1);
   scanf("%d",&tebak[i]);
  }
  for(j=0;j<i;j++)
  {
   while(tebak[i]==tebak[j])
   {
    printf("Anda telah menebak lubang tersebut\n");
    printf("Tebak bom ke-%d : ",i+1);
    scanf("%d",&tebak[i]);
   }
  }
 }
  
 //HITUNG
 for(j=0;j<4;j++){
  flag=0;
  for(i=0;i<4;i++)
  { 
   if(ranjau[j]==tebak[i]) flag=1;
   if(ranjau[j]==0) flag=2;
  }
  if(flag==1) scorePlayer[2]=scorePlayer[2]+1;
  else if(flag==0) scorePlayer[1]=scorePlayer[1]+1;
 
 }
 
 write(fsc,scorePlayer,sizeof(scorePlayer));

 if(counterentry<16){
 
 system("clear"); 
 

 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);
 
 //BOM
 for(i=0;i<4;i++)
 {
  printf("Bom ke-%d : ",i+1);
  scanf("%d",&ranjau[i]);
  while(ranjau[i]<0 || ranjau[i]>16) 
  { 
   printf("Lubang tersebut tidak tersedia\n");
   printf("Bom ke-%d : ",i+1);
   scanf("%d",&ranjau[i]);
  }
  for(j=0;j<counterentry;j++)
  {
   while(ranjau[i]==entry[j])
   {
    if(ranjau[i]==0) break;
    printf("Anda telah memasukkan ranjau ke lubang tersebut\n");
    printf("Bom ke-%d : ",i+1);
    scanf("%d",&ranjau[i]);
   }
  }
  if(ranjau[i]!=0) 
  {
   entry[counterentry]=ranjau[i];
   counterentry++;
  }
  if(counterentry>=16) break;
 }

 ranjau[4]=counterentry;
 write(fs,ranjau,sizeof(ranjau));
 read(fsc,scorePlayer,sizeof(scorePlayer));
 }
 }
 write(fsc,scorePlayer,sizeof(scorePlayer));
 system("clear");
 
 
 printf("PLAYER 1 (%d  -  %d) PLAYER 2\n",scorePlayer[1],scorePlayer[2]);
 
 close (fd);
 close (fc);
 close (fs);
 unlink (fifo2);
 return 0;
} 
 
 

Sekian tulisan saya kali ini. Semoga Bermanfaat!