2023.11.15 TIL
Code, Image source: The Linux Programming Interface, Michael Kerrisk
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // lock으로 초기화
```c
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexettr_t *attr);
int pthread_mutex_init(pthread_mutex_t *mutex);
```
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
tlpi-dist/threads/thread_incr_mutex.c
avail
변경 여부를 계속 확인(polling)
static int avail = 0;
// Thread a
// 변경여부 계속 확인
while (avail > 0)
avail--;
// Thread b
// 변경하기
avail++;
→ 문제점: while을 계속 돈다… CPU 계속 차지함
Condition Variable 사용
tlpi-dist/threads/prod_condvar.c
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 초기화
int pthread_cond_signal(pthread_cond_t *cond); // 1개의 thread(sleeping consumer)만 깨운다
int pthread_cond_broadcast(pthread_cond_t *cond); // 모든 thread(sleeping consumer)를 깨운다
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); // sleep...
→ sleeping consumer(waiting thread)는 자고있다가, 필요할때 깨워지면(avail > 0
)
pthread_mutex_lock(mutex1); // (1.1)
pthread_mutex_lock(mutex2); // (2.1) block
pthread_mutex_lock(mutex2); // (1.2) Thread A sleeps
pthread_mutex_lock(mutex1); // (2.2) block
C로 구현시 개발 생산성 떨어지지만 기존 코드가 이미 C인경우
extern “C”
#ifdef _cplusplus
extern "C" {
#endif
// C++ code
#ifdef _cplusplus
}
#endif
ls | wc -l
→ ls
의 결과물이 input으로 wc
로 들어간다ls
→ stdout (fd 1)wc
#include <unistd.h>
int pipe(int filedes[2]);
fork()
→ Parent의 fd 그대로 가져옴filedes[1]
에 write, child는 filedes[0]
에서 readtlpi-dist/pipes/simple_pipe.c
popen()
#include <stdio.h>
FILE *popen(const char *command, const char *mode); // shell script command, read/write mode
int pclose(FILE *stream);
tlpi-dist/pipes/popen_glob.c
mkfifo [-m mode] [pathname]
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
$ mkfifo myfifo # make fifo
$ wc -l < myfifo & # wc는 input(myfifo의 output)을 read 하기위해 기다림, background로 실행
$ ls -l | tee myfifo | sort -k5n # tee: 결과가 T 관을 통해 myfifo로도 나가고 sort(stdout)로도 간다
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
mqd_t mq_open(const char *name, int ofalg, ... /* mode_t mode, struct mq_attr *attr */ );
O_CREAT
→ Create queue if it doesn’t already existO_EXCL
→ With O_CREAT
, create queue exclusivelyO_RDONLY
→ Open for reading onlyO_WRONLY
→ Open for writing onlyO_RDWR
→ Open for reading and writingO_NONBLOCK
→ Open in nonblocking modetlpi-dist/pmsg/pmsg_create.c
#include <mqueue.h>
int mq_close(mqd_t mqdes); // close message queue descriptor
int mq_unlink(const char *name); // delete file
struct mq_attr {
long mq_flags; // options
long mq_maxmsg; // message 최대 개수
long mq_msgsize; // message 최대 size
long mq_curmsgs; // 현재 message queue에 있는 message 개수
};
tlpi-dist/pmsg/pmsg_getattr.c
#include <mqueue.h>
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio); // mq open할때 받았던 자료구조에 값 저장, read buffer, 받을 size, msg priority
tlpi-dist/pmsg/pmsg_send.c
#include <mqueue.h>
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio); // mq descripto, 받을 buffer, 받을 size, priority
mq_receive
이후 코드 수행tlpi-dist/pmsg/pmsg_receive.c
mq_msgsize
system default : 8KnumRead = mq_receive(mqd, buffer, attr.mq_mqsize, &prio);
if (numRead == -1) errExit("mq_receive");
$ ./pmsg_create -cx /mq
$ ./pmsg_send /mq msg-a 5
$ ./pmsg_send /mq msg-b 0
$ ./pmsg_send /mq msg-c 10
# 높은 priority부터
$ ./pmsg_receive /mq
Read 5 bytes; priority = 10
msg-c
$ ./pmsg_receive /mq
Read 5 bytes; priority = 5
msg-a
$ ./pmsg_recieve /mq
Read 5 bytes; priority = 0
msg-b
$ sudo mkdir /dev/mqueue
$ sudo mount -t mqueue none /dev/mqueue
(source, target)$ cd /dev/mqueue
$ cat mq
→ Message queue 정보 확인 (queue byte size 등)$ ./pmsg_send
로 보낸 byte만큼 queue에 write 되어 쌓여있음$ ./pmst_receive /mq
각각 하고나서 $ cat mq
다시 확인해보면 각각 받는 byte만큼 남은 queue size 줄어듦