• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Sysprog 13
 

Sysprog 13

on

  • 1,662 views

session 13 of the system programming course made by eglug

session 13 of the system programming course made by eglug

Statistics

Views

Total Views
1,662
Views on SlideShare
1,660
Embed Views
2

Actions

Likes
1
Downloads
32
Comments
0

1 Embed 2

http://www.linkedin.com 2

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Sysprog 13 Sysprog 13 Presentation Transcript

    • C/C++ Linux System Programming
        • Session 13
        • User-space System Programming
        • – session 3
    • Outline
      • Pipes & FIFOs
      • SysV mechanisms
      • POSIX mechanisms
    • IPC Mechanisms So Far
      • Signals
      • Exit status
      • Fork Address space
    • Pipes
      • Characteristics:
        • Single reader – single writer (uni-diriectional)
        • File descriptors (unnamed)
        • POSIX and Linux restrictions
        • Pipefs
        • SIGPIPE: No readers
        • PAGE_SIZE max (blocking write!!)
      • int pipe(int pipefd[2]);
      • int dup2(int oldfd, int newfd);
    • struct job *jp; struct nodelist *lp; int pipelen; int prevfd; int pip[2]; prevfd = -1; for (lp = n->npipe.cmdlist; lp; lp = lp->next) { ... pip[1] = -1; if (lp->next) { if (pipe(pip) < 0) { ... } } if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { ... if (pip[1] >= 0) { close(pip[0]); } if (prevfd > 0) { dup2(prevfd, 0); close(prevfd); } if (pip[1] > 1) { dup2(pip[1], 1); close(pip[1]); } /* Execute */ /* never returns */ } if (prevfd >= 0) close(prevfd); prevfd = pip[0]; close(pip[1]); }
    • FIFOs
      • Characteristics
        • Named pipes
        • File system
      • int mkfifo(const char *pathname, mode_t mode);
    • SysV Generic
      • General Interface
        • Get
          • IPC_PRIVATE or key,
            • key_t ftok(const char *pathname, int proj_id);
          • Flags: IPC_CREAT / IPC_EXCL
        • ctl
      • Specific Ops & control details
      • System-wide (named) or private
      • Owner / Creator (time)
      • Explicit removal
      • ipc()
    • SysV Semaphores
      • Resource: Array of Semaphore Primitives
      • int semget(key_t key, int nsems, int semflg);
      • Multiple critical regions
      • Multiple instances of a resource
        • Initialize to a value (# of available instances)
        • -ve to get resource, +ve to release
        • 0 means block (unless IPC_NOWAIT)
    • Semaphore control
      • int semctl(int semid, int semnum, int cmd, ...); /* union semun */
        • int val; /* SETVAL */
        • struct semid_ds *buf; /* IPC_STAT, IPC_SET */
        • unsigned short *array; /* GETALL, SETALL */
        • struct seminfo *__buf; /* IPC_INFO (Linux) */
      • Initialization: SETVAL / SETALL / IPC_SET
      • Debugging: GETVAL / GETALL / INFO / STAT
      • Removal: IPC_RMID
    • Semaphore Ops
      • int semop(int semid, struct sembuf *sops, unsigned nsops);
      • int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);
      • struct sem_buf
        • unsigned short sem_num;
        • short sem_op;
        • short sem_flg; /* SEM_UNDO, IPC_NOWAIT */
      • “Undoable” operations
    • SysV Messages
      • int msgget(key_t key, int msgflg);
      • int msgctl(int msqid, int cmd, struct msqid_ds *buf);
      • IPC_RMID, IPC_SET
      • int msgsnd(int msqid, const void msgp, size_t msgsz, int msgflg);
        • struct msgbuf {
        • long mtype; /* > 0 */
        • char mtext[1]; }
    • Msg Receival
      • ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
      • Msgtyp:
        • 0 first
        • > 0 (first of type) / MSG_EXCEPT
        • < 0 (first less than |type|)
      • Flags: MSG_NOERROR, IPC_NOWAIT, MSG_EXCEPT
    • SysV Shared Memory
      • int shmget(key_t key, size_t size, int shmflg); /* SHM_HUGETLB, SHM_NORESERVE */
      • int shmctl(int shmid, int cmd, struct shmid_ds *buf);
      • IPC_RMID: Mark for removal
      • void *shmat(int shmid, const void shmaddr, int shmflg); /* SHM_RDONLY SHM_REMAP */
      • int shmdt(const void *shmaddr);
    • static void ipcsyslog_init(void) { if (DEBUG) printf(&quot;shmget(%x, %d,...) &quot;, (int)KEY_ID, G.shm_size); G.shmid = shmget(KEY_ID, G.shm_size, IPC_CREAT | 0644); if (G.shmid == -1) { bb_perror_msg_and_die(&quot;shmget&quot;); } G.shbuf = shmat(G.shmid, NULL, 0); if (G.shbuf == (void*) -1L) { /* shmat has bizarre error return */ bb_perror_msg_and_die(&quot;shmat&quot;); } memset(G.shbuf, 0, G.shm_size); G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1; /*G.shbuf->tail = 0;*/ // we'll trust the OS to set initial semval to 0 (let's hope) G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); if (G.s_semid == -1) { if (errno == EEXIST) { G.s_semid = semget(KEY_ID, 2, 0); if (G.s_semid != -1) return; } bb_perror_msg_and_die(&quot;semget&quot;); } } static void log_to_shmem(const char *msg, int len) { int old_tail, new_tail; if (semop(G.s_semid, G.SMwdn, 3) == -1) { bb_perror_msg_and_die(&quot;SMwdn&quot;); } ... /* Circular buffer calculation */ memcpy(G.shbuf->data + old_tail, msg, k); if (semop(G.s_semid, G.SMwup, 1) == -1) { bb_perror_msg_and_die(&quot;SMwup&quot;); } } static void ipcsyslog_cleanup(void) { if (G.shmid != -1) { shmdt(G.shbuf); } if (G.shmid != -1) { shmctl(G.shmid, IPC_RMID, NULL); } if (G.s_semid != -1) { semctl(G.s_semid, 0, IPC_RMID, 0); } }
    • POSIX Generic
      • Filesystem like
      • Focus on the unified interface
        • May be not as versatile (do you care?)
        • Still some specifics
      • Newer, e.g.
        • mq_ in >= 2.6.6
        • Shm_ in 2.4 was on mounted /dev/shm
    • POSIX Semaphores
      • sem_t *sem_open(const char *name, int oflag);
      • sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
      • int sem_destroy(sem_t *sem);
      • int sem_init(sem_t *sem, int pshared, unsigned int value);
    • Semaphore Ops
      • int sem_wait(sem_t *sem);
      • int sem_trywait(sem_t *sem);
      • int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
      • int sem_post(sem_t *sem);
      • int sem_getvalue(sem_t *sem, int *sval);
    • POSIX Message Queues
      • mqd_t mq_open(const char *name, int oflag);
      • mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);
      • ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);
      • mqd_t mq_close(mqd_t mqdes);
      • mqd_t mq_unlink(const char *name);
    • Mq Attributes
      • mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
      • mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);
      • mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
        • {long mq_flags; /* 0 or O_NONBLOCK */
        • long mq_maxmsg;
        • long mq_msgsize;
        • long mq_curmsgs; };
    • POSIX Shared Memory
      • int shm_open(const char *name, int oflag, mode_t mode);
      • int shm_unlink(const char *name);
      • From then on, mapping
    • Memory Mapping for Shared memory
      • void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); /* MAP_SHARED */
      • int munmap(void *start, size_t length);
      • void *mremap(void *old_address, size_t old_size, size_t new_size, int flags);
    • POSIX shm example int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { char fn[32]; int fd = -1; struct shm_marker *marker; pa_random(&m->id, sizeof(m->id)); segment_name(fn, sizeof(fn), m->id); if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode & 0444)) < 0) { ... } m->size = size + PA_ALIGN(sizeof(struct shm_marker)); if (ftruncate(fd, m->size) < 0) { ... } if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { ... } marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - PA_ALIGN(sizeof(struct shm_marker))); pa_atomic_store(&marker->pid, (int) getpid()); pa_atomic_store(&marker->marker, SHM_MARKER); ... m->do_unlink = 1; } void pa_shm_free(pa_shm *m) { ... if (munmap(m->ptr, m->size) < 0) pa_log(&quot;munmap() failed: %s&quot;, pa_cstrerror(errno)); if (m->do_unlink) { char fn[32]; segment_name(fn, sizeof(fn), m->id); if (shm_unlink(fn) < 0) pa_log(&quot; shm_unlink(%s) failed: %s&quot;, fn, pa_cstrerror(errno)); } ... memset(m, 0, sizeof(*m)); } struct shm_marker { pa_atomic_t marker; /* 0xbeefcafe */ pa_atomic_t pid; void *_reserverd1; void *_reserverd2; void *_reserverd3; void *_reserverd4; }; static char *segment_name(char *fn, size_t l, unsigned id) { pa_snprintf(fn, l, &quot;/pulse-shm-%u&quot;, id); return fn; }
    • struct pa_semaphore { sem_t sem; }; pa_semaphore* pa_semaphore_new(unsigned value) { pa_semaphore *s; s = pa_xnew(pa_semaphore, 1); &s->sem, 0, value); return s; } void pa_semaphore_free(pa_semaphore *s) { sem_destroy(&s->sem) ; } void pa_semaphore_post(pa_semaphore *s) { sem_post(&s->sem) ; } void pa_semaphore_wait(pa_semaphore *s) { int ret; do { ret = sem_wait(&s->sem); } while (ret < 0 && errno == EINTR); } pa_mempool* pa_mempool_new(int shared) { pa_mempool *p; ... p = pa_xnew(pa_mempool, 1); p->semaphore = pa_semaphore_new(0); p->block_size = PA_PAGE_ALIGN(PA_MEMPOOL_SLOT_SIZE); ... if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) { } ... return p; } void pa_mempool_free(pa_mempool *p) { ... pa_shm_free(&p->memory); ... pa_semaphore_free(p->semaphore); pa_xfree(p); } static void memblock_wait(pa_memblock *b) { if (pa_atomic_load(&b->n_acquired) > 0) { pa_atomic_inc(&b->please_signal); while (pa_atomic_load(&b->n_acquired) > 0) pa_semaphore_wait(b->pool->semaphore); pa_atomic_dec(&b->please_signal); } } void pa_memblock_release(pa_memblock *b) { int r; r = pa_atomic_dec(&b->n_acquired); pa_assert(r >= 1); if (r == 1 && pa_atomic_load(&b->please_signal)) pa_semaphore_post(b->pool->semaphore); }