21 Mayıs 2021 Cuma

epoll metodu

Giriş
Şu satırı dahil ederiz.
#include <sys/epoll.h>
epoll neden Önemli
Açıklaması şöyle
2002 — LINUX releases epoll API
The 2.5.44 release of LINUX included a new API: epoll. The epoll API delivered effectively constant socket look-up time. If networking software used epoll and multiplexed connections across a handful of threads at most (as opposed to 1 thread per request), one could expect significantly better resource utilization on a server and handle 10K simultaneous connections well. This solution reduced the latency of packet routing within Linux, which enabled better scalability of open connections.
Kullanım
1. epoll_create() ile bir epollfd yarat
2. epoll_event yapısını socket fd ile doldur ve epoll_ctl() ile izlemeye başla
3. Döngü içinde epoll_wait metoduu sürekli çağır
4. Event tipine bakarak (EPOLLERR,EPOLLHUP,EPOLLIN,EPOLLOUT) socketler üzerinde işlem yap
5. Ya da socket fd'ye bakarak fd ile işlem yap. Bu yöntem sadece bir kerelik cevap veren sunucu yazılımlarda kullanılabilir.

Tasarım Hatası
epoll tasarım hatası ile ilgili bir açıklama şöyle. Bu yazıyı ilk kez bu sorudaki linkte gördüm. Kısaca dup ile çoklanan bir file descriptor close() metodu ile kapatılsa bile epoll açısından kapanmadığı için halen event'leri bildiriyor diyor.
epoll is broken because it mistakes the "file descriptor" with the underlying kernel object (the "file description"). The issue shows up when relying on the close() semantics to clean up the epoll subscriptions.

epoll_ctl(EPOLL_CTL_ADD) doesn't actually register a file descriptor. Instead it registers a tuple1 of a file descriptor and a pointer to underlying kernel object. Most confusingly the lifetime of an epoll subscription is not tied to the lifetime of a file descriptor. It's tied to the life of the kernel object.

Due to this implementation quirk calling close() on a file descriptor might or might not trigger epoll unsubscription. If the close call removes the last pointer to kernel object and causes the object to be freed, then it will cause epoll subscription cleanup. But if there are more pointers to kernel object, more file descriptors, in any process on the system, then close will not cause the epoll subscription cleanup. It is totally possible to receive events on previously closed file descriptors.
1. epoll_create metodu - size
Örnek ver

2. epoll_create1 metodu - flags
Örnek
Şöyle yaparız.
int epollfd = epoll_create1(0);
if (epollfd == -1)
{
  perror ("epoll_create");
  ...
}
Örnek
Şöyle yaparız.
int efd = epoll_create1 (EPOLL_CLOEXEC);
3. epoll_ctl metodu
epoll_ctl metodu yazısına taşıdım

4. epoll_event yapısı
Şöyle tanımlarız.
struct epoll_event events[MAXEVENTS];
events Alanı
Şu değerlerden birisi olabilir
EPOLLIN
EPOLLIN = 1 ise oku

EPOLLRDHUP
EPOLLRDHUP = 1 ise kapat. EPOLLRDHUP açıklamasını buradan aldım.
EPOLLRDHUP (since Linux 2.6.17)
Stream socket peer closed connection, or shut down writing half of connection. (This flag is especially useful for writing simple code to detect peer shutdown when using Edge Triggered monitoring.)
Örnek
Şöyle yaparız.
int servFd = socket (...);

struct epoll_event epollEvt;
epollEvt.events = EPOLLIN | EPOLLRDHUP;
epollEvt.data.u32 = servFd;
data Alanı
epoll_data tipindendir

epoll_data yapısı
epoll_event yapısının bir alanıdır. İçi şöyledir.
typedef union epoll_data {
  void        *ptr;
  int          fd;
  uint32_t     u32;
  uint64_t     u64;
} epoll_data_t;
Örnek
fd alanını kullanmak için şöyle yaparız.
epoll_event ev;
ev.data.fd = timerfd;
Örnek
ptr alanını kullanmak için bir ata sınıf tanımlarız.
class EventHandler {
public:
  virtual ~EventHandler() = default;
  virtual int fd() const = 0;
  virtual void fire() = 0;
};
Bu ata sınıfı ptr alanına vererek epoll() çağrısına dahil ederiz.
EventHandler* handler = new TimerHandler();
ev.data.ptr = handler;
epoll_ctl(epollfd, EPOLL_CTL_ADD, handler->fd(), &ev);
Sonuçları dolaşırken şöyle yaparız
int n = epoll_wait (epollfd, events , num_events, -1 ); 
for (int i = 0; i < n; ++i) {
  static_cast<EventHandler*>(events[i].data.ptr)->fire();
}
5. epoll_wait metodu
Şöyle yaparız.
int n = epoll_wait (epollfd, events, MAXEVENTS, -1);
Örnek
Sonucu dolaşmak için şöyle yaparız.
int n = epoll_wait (epollfd, events , num_events, -1 ); 
for (int i = 0; i < n; ++i) {
  if (events[i].data.fd == timerfd) {
    handle_timer_callback();
  }
  else {
    // something else
  }
}
Örnek
Sonucu dolaşmak için şöyle yaparız.
for (i = 0; i < n; i++)
{
  int fd = events[i].data.fd;

  if ((events[i].events & EPOLLERR) ||
      (events[i].events & EPOLLHUP))
  {
    /* An error has occured on this fd, or the socket is not
       ready for reading (why were we notified then?) */

    close(fd);
    
  }
  else if (fd == listendf && (events[i].events & EPOLLIN))
  {
    /* We have a notification on the listening socket, which
       means one or more incoming connections. */
    HandleAccept(epollfd, listenfd);
  }
  else if(events[i].events & EPOLLIN)
  {
    /* We have data on the fd waiting to be read. Read and
       display it. We must read whatever data is available
       completely, as we are running in edge-triggered mode
       and won't get a notification again for the same
       data. */

    HandleRead(epollfd, fd);
  }
  else if (events[i].events & EPOLLOUT)
  {
    ...
  }
}
Örnek
Şöyle yaparız.
for (;;) {
  struct epoll_event pollEvent[512];
  int eventCount = epoll_wait (efd, pollEvent, 512, -1);
  for (int i = 0; i < eventCount; ++i) {
    struct epoll_event* curEvent = &pollEvent[i];
    if (curEvent->data.u32 == servFd) {
      int clientFd = accept4 (servFd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
      struct epoll_event epollEvt;
      epollEvt.events = EPOLLIN | EPOLLRDHUP | EPOLLET;
      epollEvt.data.u32 = clientFd;
      epoll_ctl (efd, EPOLL_CTL_ADD, clientFd, &epollEvt);
      continue;
    }

    int clientFd = curEvent->data.u32;
    char recvBuffer[2048];
    recvfrom (clientFd, recvBuffer, 2048, 0, NULL, NULL);
    char sndMsg[] = "...";
    size_t sndMsgLength = sizeof (sndMsg) - 1;
    struct iovec sndBuffer;
    sndBuffer.iov_base = sndMsg;
    sndBuffer.iov_len = sndMsgLength;
    writev (clientFd, &sndBuffer, 1);
    close (clientFd);
  }
}

18 Mayıs 2021 Salı

ntp_gettime metodu - NTP saatini verir

Örnek
Linux'ta NTP saati şöyle alınabilir.
#include <stdio.h>
 #include <sys/timex.h>
 #include <sys/time.h>

 int main(int argc, char **argv) 
 {
     struct timeval tv; 
     gettimeofday(&tv, NULL);

     struct ntptimeval ntptv;
     ntp_gettime(&ntptv);

     printf("gettimeofday: tv_sec = %ld, tv_usec = %ld\n", 
                tv.tv_sec, tv.tv_usec);
     printf("ntp_gettime:  tv_sec = %ld, tv_usec = %ld\n", 
                ntptv.time.tv_sec, ntptv.time.tv_usec);
 }
Çıktı olarak şunu görürüz.
gettimeofday: tv_sec = 1366209548, tv_usec = 137736    //microsecond
ntp_gettime:  tv_sec = 1366209548, tv_usec = 137743081 //nanosecond
Burada NTP sunucusundan zamanı çekip, sistem saati ile farkını bulmayı gösteren bir örnek var.

14 Mayıs 2021 Cuma

ntp_adjtime metodu - NTP sunucusu ile senkronize olup olmadığımızı döndürür

Giriş
NTP sunucusu ile senkronize olup olmadığımızı döndürür.
Örnek
Şöyle yaparız
#include <stdio.h>
#include <sys/timex.h>

int main()
{
    struct timex timex_info = {};
    timex_info.modes = 0;         /* explicitly don't adjust any time parameters */

    int ntp_result = ntp_adjtime(&timex_info);

    printf("Max       error: %9ld (us)\n", timex_info.maxerror);
    printf("Estimated error: %9ld (us)\n", timex_info.esterror);
    printf("Clock precision: %9ld (us)\n", timex_info.precision);
    printf("Jitter:          %9ld (%s)\n", timex_info.jitter,
           (timex_info.status & STA_NANO) ? "ns" : "us");
    printf("Synchronized:    %9s\n", 
           (ntp_result >= 0 && ntp_result != TIME_ERROR) ? "yes" : "no");
    return 0;
}

12 Nisan 2021 Pazartesi

convert komutu

Giriş
Dosyaları farklı formatlara çevirir

Örnek - PDF'ten JPG formatına
Şöyle yaparız
convert file.pdf file.jpg

5 Nisan 2021 Pazartesi

find komutu regex seçeneği

Giriş
Açıklaması şöyle
Test: -regex expr
Test: -iregex expr
True if the entire file name matches regular expression expr. This is a match on the whole path, not a search. […]
-iregex seçeneği
Örnek
Şöyle yaparız
find . -type f -iregex '.*\.tiff?'
regex seçeneği
Örnek
Elimizde şöyle bir komut olsun. Bu komut büyük harli dosyaları seçmeye çalışıyor ancak çıktısı boştur. Çünkü regex tüm path için uygulanıyr.
find /tmp/txz/httperf/httperf-20210403git/ -regextype posix-egrep -regex [A-Z][A-Z]$
Düzeltmek için şöyle yaparız
find /tmp/txz/httperf/httperf-20210403git/ |egrep [A-Z][A-Z]$ 
/tmp/txz/httperf/httperf-20210403git/.git/refs/remotes/origin/HEAD
/tmp/txz/httperf/httperf-20210403git/.git/logs/refs/remotes/origin/HEAD
/tmp/txz/httperf/httperf-20210403git/.git/logs/HEAD
/tmp/txz/httperf/httperf-20210403git/.git/HEAD
/tmp/txz/httperf/httperf-20210403git/NEWS
/tmp/txz/httperf/httperf-20210403git/COPYRIGHT
/tmp/txz/httperf/httperf-20210403git/AUTHORS
/tmp/txz/httperf/httperf-20210403git/TODO
/tmp/txz/httperf/httperf-20210403git/src/lib/README

29 Mart 2021 Pazartesi

inode Nedir

Her Dosya Sisteminde inode Yoktur
Açıklaması şöyle
For virtual, volatile, or inode-agnostic filesystems, inode numbers are usually generated from a monotonically incrementing, 32-bit counter when the inode is created. The rest of the inode (eg. permissions) is built from the equivalent data in the underlying filesystem, or is replaced with values set at mount time (eg. {uid,gid}=) if no such concept exists.
Örnek - VFAT
Elimizde bir VFAT dosya sistemi olsun. Şöyle yaparız. Burada inode değerlerinin üretildiği görülebilir.
% ls -li
合計 736
1207 drwxr-xr-x 3 root root  16384  3月 10 10:42 efi
1208 -rwxr-xr-x 1 root root 721720  3月 22 14:15 kernel.bin

5 Mart 2021 Cuma

google-chrome komutu

--dump-dom seçeneği
Sayfanın görüntüsünü HTML olarak alabilmeyi sağlar. Böylece sayfadaki JavaScript kodları kaydedilmez.
Örnek
Şöyle yaparız
google-chrome --headless --dump-dom 'URL' > ~/file.html