- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2018-03-25T09:07:49+00:00","default:haikikyou","haikikyou")
[[Unix-Linux]]
* Read-Write Lock [#fcad82f1]
&label(study){実験}; ''共有メモリ上でのpthread_rwlock''
shared設定するとプロセス間でmutexを利用することができる。Read-Writeロックについて、Linuxではwriteロック待ちのスレッドがいても、readロックが取得できてしまう?現象があるようだ。これについては、非標準の&code(){PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP};を指定すると回避できる(実際に利用する場合には、各プラットフォームで要検証)
#geshi(c,number){{{
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <sys/shm.h>
#include <string.h>
#define CHILD_NUM 4
#define IPCProtection (0600)
#define MAX_SHMEM 3
#define BUFSIZE 128
/*
* Shared memory
*/
typedef struct Shm
{
int shmid;
void *memaddr;
} Shm;
static Shm shmem[MAX_SHMEM];
static int shmem_idx = 0;
/* pointer on shared memory */
static pthread_rwlock_t *rwlock;
static char *shared_data;
volatile int* shutdown_flag;
/* child processes */
static pid_t child_procs[CHILD_NUM];
/* my process id */
static int myid;
static pid_t spawn(void);
static void do_it(void);
static void wait_children(void);
static void kill_all_children(int sig);
static void* shmem_create(int idx, size_t size);
static void shmem_detach(void);
static void shmem_destroy(void);
static pid_t spawn(void)
{
pid_t pid;
pid = fork();
if (pid < 0) {
perror("failed to fork");
exit(1);
} else if (pid == 0) {
myid = getpid();
do_it();
}
return pid;
}
static void do_it(void)
{
char buf[BUFSIZE];
for (;;)
{
pthread_rwlock_rdlock(rwlock);
{
//pthread_rwlock_rdlock(rwlock); /* DeadLock!! */
memcpy(buf, shared_data, BUFSIZE);
printf("child[%d]: %ld: %s\n", myid, time(NULL), buf);
fflush(stdout);
memset(buf, 0, sizeof(buf));
}
pthread_rwlock_unlock(rwlock);
if (*shutdown_flag == 1)
break;
sleep(1);
}
shmem_detach();
exit(0);
}
static void kill_all_children(int sig)
{
int i;
for (i = 0; i < CHILD_NUM; ++i)
{
if (child_procs[i] != 0)
kill(child_procs[i], sig);
}
}
static void wait_children(void)
{
pid_t pid;
int status;
do {
pid = waitpid(-1, &status, 0);
} while (pid > 0 || errno == EINTR);
}
static void* shmem_create(int idx, size_t size)
{
if (MAX_SHMEM <= idx)
return NULL;
shmem[idx].shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | IPCProtection);
if (shmem[idx].shmid < 0) {
perror("main : shmget ");
return NULL;
}
shmem[idx].memaddr = shmat(shmem[idx].shmid, NULL, 0);
if (shmem[idx].memaddr == (void *) -1) {
perror("main : shmat ");
shmctl(shmem[idx].shmid, IPC_RMID, NULL);
return NULL;
}
return shmem[idx].memaddr;
}
static void shmem_detach(void)
{
int i;
for (i = 0; i < MAX_SHMEM; ++i)
{
if (shmdt((void *) shmem[i].memaddr) < 0)
{
perror("main : shmdt ");
}
}
}
static void shmem_destroy(void)
{
int i;
for (i = 0; i < shmem_idx; ++i)
{
if (shmdt((void *) shmem[i].memaddr) < 0)
{
perror("main : shmdt ");
}
if (shmctl(shmem[i].shmid, IPC_RMID, NULL) < 0)
{
perror("main : shmctl ");
}
}
}
int main(int argc, char *argv[])
{
int i;
pthread_rwlockattr_t attrrwlock;
pthread_rwlockattr_init(&attrrwlock);
/* This setting is needed on Linux. */
#ifdef __USE_UNIX98
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
#endif
pthread_rwlockattr_setpshared(&attrrwlock, PTHREAD_PROCESS_SHARED);
rwlock = shmem_create(shmem_idx++, sizeof(pthread_rwlock_t));
if (rwlock == NULL) {
perror("main : shmat ");
exit(EXIT_FAILURE);
}
if (pthread_rwlock_init(rwlock, &attrrwlock))
{
perror("main: pthread_rwlock_init ");
exit(EXIT_FAILURE);
}
pthread_rwlockattr_destroy(&attrrwlock);
shared_data = shmem_create(shmem_idx++, BUFSIZE);
if (shared_data == NULL) {
perror("main: shmat ");
exit(EXIT_FAILURE);
}
shutdown_flag = shmem_create(shmem_idx++, sizeof(int));
if (shutdown_flag == NULL) {
perror("main: shmat ");
exit(EXIT_FAILURE);
}
*shutdown_flag = 0;
for (i = 0; i < CHILD_NUM; ++i)
child_procs[i] = spawn();
int retries = 5;
char* messages[] = {
"hello", "world", "foo", "bar", "oops!"
};
setbuf(stdout, NULL);
while (retries-- > 0)
{
char *m = messages[retries % 5];
pthread_rwlock_wrlock(rwlock);
{
strncpy(shared_data, m, strlen(m));
sleep(2);
}
pthread_rwlock_unlock(rwlock);
sleep(1);
}
*shutdown_flag = 1;
kill_all_children(SIGTERM);
wait_children();
shmem_destroy();
puts("done");
exit(0);
}
}}}
&label(warn){参考};
- [[GNU/Linux でのスレッドプログラミング>http://www.tsoftware.jp/nptl/]] - &size(11){&color(gray){on http://www.tsoftware.jp/nptl/};};
- [[Linux上でのマルチスレッドプログラミングの注意点>https://www.soum.co.jp/misc/individual/multi-thread/]] - &size(11){&color(gray){on https://www.soum.co.jp/misc/individual/multi-thread/};};
- [[Man page of PTHREAD_RWLOCKATTR_SETKIND_NP>https://linuxjm.osdn.jp/html/LDP_man-pages/man3/pthread_rwlockattr_setkind_np.3.html]] - &size(11){&color(gray){on https://linuxjm.osdn.jp/html/LDP_man-pages/man3/pthread_rwlockattr_setkind_np.3.html};};
- [[pthread_rwlockattr_setpshared() - プロセス共用読み取りまたは書き込みロック属性の設定>https://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxbd00/rp0ras.htm]] - &size(11){&color(gray){on https://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxbd00/rp0ras.htm};};
- [[マルチスレッドのプログラミング pthread_rwlockattr_setpshared(3T)>https://docs.oracle.com/cd/E19455-01/806-2732/sync-58/index.html]] - &size(11){&color(gray){on https://docs.oracle.com/cd/E19455-01/806-2732/sync-58/index.html};};
- [[FreeBSD Manual Pages (pthread_rwlockattr_setpshared)>https://www.freebsd.org/cgi/man.cgi?query=pthread_rwlockattr_setpshared&sektion=3&manpath=FreeBSD+11.1-stable]] - &size(11){&color(gray){on https://www.freebsd.org/cgi/man.cgi?query=pthread_rwlockattr_setpshared&sektion=3&manpath=FreeBSD+11.1-stable};};
- [[pthread_rwlockattr_setpshared(3) - Linux man page>https://linux.die.net/man/3/pthread_rwlockattr_setpshared]] - &size(11){&color(gray){on https://linux.die.net/man/3/pthread_rwlockattr_setpshared};};
* シグナル [#d3efd0cb]
スレッドごとにシグナルマスクを持つ。シグナルはプロセスに送られ、複数のスレッドがいる場合は、実行中の任意のスレッドに送られる。どのスレッドが捕捉するかはシグナルマスクによる。特定のスレッドにシグナルを処理して欲しい場合は、他のスレッドでシグナルをブロックすればよい。
マルチスレッドプログラムでシグナルをマスクする場合、&code(){pthread_sigmask}; 関数を使用する。マルチスレッドプログラムで、&code(){sigprocmask};関数を使用した場合の動作は未定義となっている。
#geshi(c,number){{{
}}}
* 参考リンク [#cb5aa206]
- [[Linuxとpthreadsによる マルチスレッドプログラミング入門 (プログラミング基礎講座)>http://www.amazon.co.jp/exec/obidos/ASIN/4798053724/haikikyou-22/ref=nosim]] - &size(11){&color(gray){on http://www.amazon.co.jp/};};
- [[Pthreadsプログラミング>http://www.amazon.co.jp/exec/obidos/ASIN/4900900664/haikikyou-22/ref=nosim/]] - &size(11){&color(gray){on http://www.amazon.co.jp/};};
- [[Man page of PTHREADS>https://linuxjm.osdn.jp/html/LDP_man-pages/man7/pthreads.7.html]] - &size(11){&color(gray){on https://linuxjm.osdn.jp/html/LDP_man-pages/man7/pthreads.7.html};};
- [[Multithreaded Programming (POSIX pthreads Tutorial)>https://randu.org/tutorials/threads/]] - &size(11){&color(gray){on https://randu.org/tutorials/threads/};};
- [[POSIX thread (pthread) libraries>https://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html]] - &size(11){&color(gray){on https://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html};};
- [[マルチスレッドのプログラミング>https://docs.oracle.com/cd/E19455-01/806-2732/index.html]] - &size(11){&color(gray){on https://docs.oracle.com/cd/E19455-01/806-2732/index.html};};
- [[POSIXスレッド(2)>http://www.hpcs.cs.tsukuba.ac.jp/~tatebe/lecture/h22/syspro/l7-thread.pdf]] - &size(11){&color(gray){on http://www.hpcs.cs.tsukuba.ac.jp/~tatebe/lecture/h22/syspro/l7-thread.pdf};};
- [[マルチスレッド・プログラミング(1)/ Multithread programming (1)>http://www.cs.tsukuba.ac.jp/~yas/cs/csys-2013/2013-10-08/]] - &size(11){&color(gray){on http://www.cs.tsukuba.ac.jp/~yas/cs/csys-2013/2013-10-08/};};
- [[CITO Research 2010 年 7 月 マルチコアのジレンマ ホワイト ペーパー>https://www.agtech.co.jp/products/pervasive/psql/v11/pdf/WP_The_Multi-core_Dilemma.pdf]] - &size(11){&color(gray){on https://www.agtech.co.jp/products/pervasive/psql/v11/pdf/WP_The_Multi-core_Dilemma.pdf};};
- [[GNU/Linux でのスレッドプログラミング>http://www.tsoftware.jp/nptl/]]- &size(11){&color(gray){on http://www.tsoftware.jp/nptl/};};
- Pthreadのスタック
-- [[スタックオーバーフローのハンドリング (Stack Overflow Handling)>http://www.nminoru.jp/~nminoru/programming/stackoverflow_handling.html]] - &size(11){&color(gray){on http://www.nminoru.jp/~nminoru/programming/stackoverflow_handling.html};};
- 非同期シグナルセーフな関数
-- [[2.4.3 Signal Actions(非同期シグナルセーフな関数)>http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03]] - &size(11){&color(gray){on http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html};};
-- [[Linux - Man Page of Signal >https://linuxjm.osdn.jp/html/LDP_man-pages/man7/signal.7.html]] - &size(11){&color(gray){on https://linuxjm.osdn.jp/html/LDP_man-pages/man7/signal.7.html};};
-- [[fork(The Open Group Base Specifications Issue 6)>http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html]] - &size(11){&color(gray){on http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html};};
-- [[JPCERT/CC - SIG30-C. シグナルハンドラ内では非同期安全な関数のみを呼び出す>https://www.jpcert.or.jp/sc-rules/c-sig30-c.html]] - &size(11){&color(gray){on https://www.jpcert.or.jp/sc-rules/c-sig30-c.html};};