[태그:] semaphore

  • posix shared memory, p325~p335

    fork로 나온 parent, child와 다르게 완전 다른 프로세스간 shared memory로 데이터를 공유할 수 있다.

    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ cat make_memory.c 
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #define FILE_MODE 0666
    
    int
    main(int argc, char **argv)
    {
    	int		c, fd, flags;
    	char	*ptr;
    	off_t	length;
    
    	flags = O_RDWR | O_CREAT;
    	while ( (c = getopt(argc, argv, "e")) != -1) {
    		switch (c) {
    		case 'e':
    			flags |= O_EXCL;
    			break;
    		}
    	}
    	if (optind != argc - 2)
    		perror("usage: shmcreate [ -e ] <name> <length>");
    	length = atoi(argv[optind + 1]);
    
    	fd = shm_open(argv[optind], flags, FILE_MODE);
    	ftruncate(fd, length);
    
    	ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    	exit(0);
    }
    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ cat unlink.c 
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #define FILE_MODE 0666
    
    
    
    int
    main(int argc, char **argv)
    {
    	if (argc != 2)
    		perror("usage: shmunlink <name>");
    
    	shm_unlink(argv[1]);
    
    	exit(0);
    }
    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ cat write.c 
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #define FILE_MODE 0666
    
    int
    main(int argc, char **argv)
    {
    	int		i, fd;
    	struct stat	stat;
    	unsigned char	*ptr;
    
    	if (argc != 2)
    		perror("usage: shmwrite <name>");
    
    		/* 4open, get size, map */
    	fd = shm_open(argv[1], O_RDWR, FILE_MODE);
    	fstat(fd, &stat);
    	ptr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE,
    			   MAP_SHARED, fd, 0);
    	close(fd);
    
    		/* 4set: ptr[0] = 0, ptr[1] = 1, etc. */
    	for (i = 0; i < stat.st_size; i++)
    		*ptr++ = i % 256;
    
    	exit(0);
    }
    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ cat read.c 
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #define FILE_MODE 0400
    
    int
    main(int argc, char **argv)
    {
    	int		i, fd;
    	struct stat	stat;
    	unsigned char	c, *ptr;
    
    	if (argc != 2)
    		perror("usage: shmread <name>");
    
    		/* 4open, get size, map */
    	fd = shm_open(argv[1], O_RDONLY, FILE_MODE);
    	fstat(fd, &stat);
    	ptr = mmap(NULL, stat.st_size, PROT_READ,
    			   MAP_SHARED, fd, 0);
    	close(fd);
    
    		/* 4check that ptr[0] = 0, ptr[1] = 1, etc. */
    	for (i = 0; i < stat.st_size; i++)
    		if ( (c = *ptr++) == (i % 256))
    			printf("ptr[%d] = %d\n", i, c);
    
    	exit(0);
    }

    이를 실행하면 다음과 같다. 512 길이 메모리를 할당하고, 250~259번지를 보면 다시 0으로 돌아간다. od로 확인하면 255에서 0으로 갔음을 본다. 파일 사용하는 방법과 비슷하다.

    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ ./makemeory test 512
    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ ./write test
    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ od -A d -t u1 -t x2 /dev/shm/test 
    0000000   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
               0100    0302    0504    0706    0908    0b0a    0d0c    0f0e
    0000016  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
               1110    1312    1514    1716    1918    1b1a    1d1c    1f1e
    0000032  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47
               2120    2322    2524    2726    2928    2b2a    2d2c    2f2e
    0000048  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63
               3130    3332    3534    3736    3938    3b3a    3d3c    3f3e
    0000064  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79
               4140    4342    4544    4746    4948    4b4a    4d4c    4f4e
    0000080  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95
               5150    5352    5554    5756    5958    5b5a    5d5c    5f5e
    0000096  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111
               6160    6362    6564    6766    6968    6b6a    6d6c    6f6e
    0000112 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
               7170    7372    7574    7776    7978    7b7a    7d7c    7f7e
    0000128 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
               8180    8382    8584    8786    8988    8b8a    8d8c    8f8e
    0000144 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
               9190    9392    9594    9796    9998    9b9a    9d9c    9f9e
    0000160 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
               a1a0    a3a2    a5a4    a7a6    a9a8    abaa    adac    afae
    0000176 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
               b1b0    b3b2    b5b4    b7b6    b9b8    bbba    bdbc    bfbe
    0000192 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
               c1c0    c3c2    c5c4    c7c6    c9c8    cbca    cdcc    cfce
    0000208 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
               d1d0    d3d2    d5d4    d7d6    d9d8    dbda    dddc    dfde
    0000224 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
               e1e0    e3e2    e5e4    e7e6    e9e8    ebea    edec    efee
    0000240 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
               f1f0    f3f2    f5f4    f7f6    f9f8    fbfa    fdfc    fffe
    0000256   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
               0100    0302    0504    0706    0908    0b0a    0d0c    0f0e
    0000272  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
               1110    1312    1514    1716    1918    1b1a    1d1c    1f1e
    0000288  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47
               2120    2322    2524    2726    2928    2b2a    2d2c    2f2e
    0000304  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63
               3130    3332    3534    3736    3938    3b3a    3d3c    3f3e
    0000320  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79
               4140    4342    4544    4746    4948    4b4a    4d4c    4f4e
    0000336  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95
               5150    5352    5554    5756    5958    5b5a    5d5c    5f5e
    0000352  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111
               6160    6362    6564    6766    6968    6b6a    6d6c    6f6e
    0000368 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
               7170    7372    7574    7776    7978    7b7a    7d7c    7f7e
    0000384 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
               8180    8382    8584    8786    8988    8b8a    8d8c    8f8e
    0000400 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
               9190    9392    9594    9796    9998    9b9a    9d9c    9f9e
    0000416 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
               a1a0    a3a2    a5a4    a7a6    a9a8    abaa    adac    afae
    0000432 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
               b1b0    b3b2    b5b4    b7b6    b9b8    bbba    bdbc    bfbe
    0000448 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
               c1c0    c3c2    c5c4    c7c6    c9c8    cbca    cdcc    cfce
    0000464 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
               d1d0    d3d2    d5d4    d7d6    d9d8    dbda    dddc    dfde
    0000480 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
               e1e0    e3e2    e5e4    e7e6    e9e8    ebea    edec    efee
    0000496 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
               f1f0    f3f2    f5f4    f7f6    f9f8    fbfa    fdfc    fffe
    0000512
    pi@raspberrypi:~/Project/cCode/IPC/shared_memory $ ./read test | grep -e "ptr\[25[0-9]\]"
    ptr[250] = 250
    ptr[251] = 251
    ptr[252] = 252
    ptr[253] = 253
    ptr[254] = 254
    ptr[255] = 255
    ptr[256] = 0
    ptr[257] = 1
    ptr[258] = 2
    ptr[259] = 3
  • shared memory introduction, p303 ~ p315

    semaphore로 process간 데이터를 주고 받을 줄 알았는데, 아니었다. semaphore로 동기하고 process간 데이터 전달은 메모리 공유로 한다.

    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #define	SEM_NAME	"mysem"
    #define FILE_MODE 0666
    struct shared{
    	sem_t mutex;
    	int count;
    } shared;
    
    int
    main(int argc, char **argv)
    {
    	int		fd, i, nloop, zero = 0;
    	//int		*ptr;
    	//sem_t	*mutex;
    	struct shared *ptr;
    
    	if (argc != 3)
    		perror("usage: incr2 <pathname> <#loops>");
    	nloop = atoi(argv[2]);
    
    		/* 4open file, initialize to 0, map into memory */
    	fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE);
    	write(fd, &shared, sizeof(struct shared));
    	ptr = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    	close(fd);
    
    		/* 4create, initialize, and unlink semaphore */
    	//mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1);
    	sem_init(&ptr->mutex,1,1);
    
    
    	sem_unlink(SEM_NAME);
    
    	setbuf(stdout, NULL);	/* stdout is unbuffered */
    	if (fork() == 0) {		/* child */
    		for (i = 0; i < nloop; i++) {
    			sem_wait(&ptr->mutex);
    			printf("child: %d\n", (ptr->count)++);
    			sem_post(&ptr->mutex);
    		}
    		exit(0);
    	}
    
    		/* 4parent */
    	for (i = 0; i < nloop; i++) {
    		sem_wait(&ptr->mutex);
    		printf("parent: %d\n", ptr->count++);
    		sem_post(&ptr->mutex);
    	}
    	exit(0);
    }
    
    pi@raspberrypi:~/Project/cCode/IPC $ ./a.out tt 100
    parent: 0
    parent: 1
    parent: 2
    parent: 3
    parent: 4
    parent: 5
    child: 6
    child: 7
    child: 8
    child: 9
    child: 10
    child: 11
    child: 12
    child: 13
    child: 14
    child: 15
    child: 16
    child: 17
    child: 18
    child: 19
    child: 20
    child: 21
    child: 22
    child: 23
    child: 24
    child: 25
    child: 26
    child: 27
    child: 28
    child: 29
    child: 30
    child: 31
    child: 32
    child: 33
    child: 34
    child: 35
    child: 36
    child: 37
    child: 38
    child: 39
    child: 40
    child: 41
    child: 42
    child: 43
    child: 44
    child: 45
    child: 46
    child: 47
    child: 48
    child: 49
    child: 50
    child: 51
    child: 52
    child: 53
    child: 54
    child: 55
    child: 56
    child: 57
    child: 58
    child: 59
    child: 60
    child: 61
    child: 62
    child: 63
    child: 64
    child: 65
    child: 66
    child: 67
    child: 68
    child: 69
    child: 70
    child: 71
    child: 72
    child: 73
    child: 74
    child: 75
    child: 76
    child: 77
    child: 78
    child: 79
    child: 80
    child: 81
    child: 82
    child: 83
    child: 84
    child: 85
    child: 86
    child: 87
    child: 88
    child: 89
    child: 90
    child: 91
    child: 92
    child: 93
    child: 94
    child: 95
    child: 96
    child: 97
    child: 98
    child: 99
    child: 100
    child: 101
    child: 102
    child: 103
    child: 104
    child: 105
    parent: 106
    parent: 107
    parent: 108
    parent: 109
    parent: 110
    parent: 111
    parent: 112
    parent: 113
    parent: 114
    parent: 115
    parent: 116
    parent: 117
    parent: 118
    parent: 119
    parent: 120
    parent: 121
    parent: 122
    parent: 123
    parent: 124
    parent: 125
    parent: 126
    parent: 127
    parent: 128
    parent: 129
    parent: 130
    parent: 131
    parent: 132
    parent: 133
    parent: 134
    parent: 135
    parent: 136
    parent: 137
    parent: 138
    parent: 139
    parent: 140
    parent: 141
    parent: 142
    parent: 143
    parent: 144
    parent: 145
    parent: 146
    parent: 147
    parent: 148
    parent: 149
    parent: 150
    parent: 151
    parent: 152
    parent: 153
    parent: 154
    parent: 155
    parent: 156
    parent: 157
    parent: 158
    parent: 159
    parent: 160
    parent: 161
    parent: 162
    parent: 163
    parent: 164
    parent: 165
    parent: 166
    parent: 167
    parent: 168
    parent: 169
    parent: 170
    parent: 171
    parent: 172
    parent: 173
    parent: 174
    parent: 175
    parent: 176
    parent: 177
    parent: 178
    parent: 179
    parent: 180
    parent: 181
    parent: 182
    parent: 183
    parent: 184
    parent: 185
    parent: 186
    parent: 187
    parent: 188
    parent: 189
    parent: 190
    parent: 191
    parent: 192
    parent: 193
    parent: 194
    parent: 195
    parent: 196
    parent: 197
    parent: 198
    parent: 199
    
    
    pi@raspberrypi:~/Project/cCode/IPC $ od -A d -t d tt
    0000000           2         128           0           0
    0000016         200
    000002
  • 다른 process간 named semaphore 사용(실패)

    세마포어로 데이터를 전달할 줄 알았으나, 동기화만 한다. 프로세스간 데이터를 공유할 방법이 없다. 다음 예제 shared memory로 공유한다. named semaphore는 잘 동작하는 듯 한데, 검증을 못했다.

    pi@raspberrypi:~/Project/cCode/IPC $ cat named_semaphore_prod.c 
    /* include main */
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <signal.h>
    #define	NBUFF	 10
    #define	SEM_MUTEX	"mutex"	 	/* these are args to px_ipc_name() */
    #define	SEM_NEMPTY	"empty"
    #define	SEM_NSTORED	"nstored"
    #define SEM_PROGEND "end"
    
    int		nitems;					/* read-only by producer and consumer */
    struct {	/* data shared by producer and consumer */
      int	buff[NBUFF];
      sem_t	*mutex, *nempty, *nstored, *endprog;
    } shared;
    
    
    static void signal_hanlder (int signo)
    {
    /*
    * Technically, you shouldn't use printf() in a
    * signal handler, but it isn't the end of the
    * world. I'll discuss why in the section
    * "Reentrancy."
    */
      if(signo == SIGINT){
        printf ("Caught SIGINT!\ndelete named semaphore\n");
    	sem_unlink(SEM_MUTEX);
    	sem_unlink(SEM_NEMPTY);
    	sem_unlink(SEM_NSTORED);
    	sem_unlink(SEM_PROGEND);
        exit (EXIT_SUCCESS);
      }
    }
    
    int
    main(int argc, char **argv)
    {
    	int		i, items;
    	errno=0;
    
    //if (argc != 2)
    //		perror("usage: prodcons1 <#items>");
    //	nitems = atoi(argv[1]);
    		/* 4create three semaphores */
    
    	//무한 루프에서 세마포어 동작..
    	//signal handler로 삭제필요.
    
    	if(signal(SIGINT, signal_hanlder) == SIG_ERR){
    		fprintf(stderr, "cannot handle SIGINT\n");
    		exit(EXIT_FAILURE);
    	}
    
    
    	shared.mutex = sem_open(SEM_MUTEX, O_CREAT | O_EXCL, 0660, 1);
    	if(shared.mutex == SEM_FAILED && errno == EEXIST ){
    		printf("delete existing semaphore mutex\n");
    		sem_unlink(SEM_MUTEX);
    		shared.mutex = sem_open(SEM_MUTEX, O_CREAT | O_EXCL, 0660, 1);
    	} //if
    
    	shared.nempty = sem_open(SEM_NEMPTY, O_CREAT | O_EXCL, 0660, NBUFF);
    	if(shared.nempty== SEM_FAILED && errno == EEXIST ){
    		printf("delete existing semaphore nempty\n");
    		sem_unlink(SEM_NEMPTY);
    		shared.nempty = sem_open(SEM_NEMPTY, O_CREAT | O_EXCL, 0660, NBUFF);
    	} //if
    
    	shared.nstored = sem_open(SEM_NSTORED, O_CREAT | O_EXCL, 0660, 0);
    	if(shared.nstored== SEM_FAILED && errno == EEXIST ){
    		printf("delete existing semaphore nstored\n");
    		sem_unlink(SEM_NSTORED);
    		shared.nstored = sem_open(SEM_NSTORED, O_CREAT | O_EXCL, 0660, 0);
    
    	} //if
    
    	shared.endprog = sem_open(SEM_PROGEND, O_RDONLY);
    	if(shared.endprog== SEM_FAILED && errno == EEXIST ){
    		printf("delete existing semaphore endprog\n");
    		sem_unlink(SEM_PROGEND);
    		shared.endprog = sem_open(SEM_PROGEND, O_RDONLY);
    
    	} //if
    	//sem_getvalue(shared.endprog, &items);
    	//printf("producer. items are %d.\n",items);
    
    
    	while(1){
    
    		sem_wait(shared.nempty);	/* wait for at least 1 empty slot */
    		sem_wait(shared.mutex);
    		shared.buff[i % NBUFF] = i;	/* store i into circular buffer */
    		items--;
    		sem_post(shared.mutex);
    		sem_post(shared.nstored);	/* 1 more stored item */
    
    
    		//프로그램 end 확인.
    		//consum에서 nitems를 받지 말고,
    		//동기화 잘 된다는 생각으로
    		//prod, consum 양쪽 카운터..
    		//목표 카운터 도달하면 모두 종료.
    		//if(items<=0) break;
    		
    	}
    
    	sem_unlink(SEM_MUTEX);
    	sem_unlink(SEM_NEMPTY);
    	sem_unlink(SEM_NSTORED);
    	sem_unlink(SEM_PROGEND);
    
    
    	return 0;
    }
    pi@raspberrypi:~/Project/cCode/IPC $ cat named_semaphore_consu.c
    /* include main */
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <errno.h>
    
    #define	NBUFF	 10
    #define	SEM_MUTEX	"mutex"	 	/* these are args to px_ipc_name() */
    #define	SEM_NEMPTY	"empty"
    #define	SEM_NSTORED	"nstored"
    #define SEM_PROGEND "end"
    
    int		nitems;					/* read-only by producer and consumer */
    struct {	/* data shared by producer and consumer */
      int	buff[NBUFF];
      sem_t	*mutex, *nempty, *nstored, *endprog;
    
    } shared;
    
    int
    main(int argc, char **argv)
    {
    	int		i;
    
    	if (argc != 2)
    		perror("usage: prodcons1 <#items>");
    	nitems = atoi(argv[1]);
    		/* 4create three semaphores */
    	shared.mutex = sem_open(SEM_MUTEX, O_RDWR);
    	shared.nempty = sem_open(SEM_NEMPTY, O_RDWR);
    	shared.nstored = sem_open(SEM_NSTORED, O_RDWR);
    	shared.endprog = sem_open(SEM_PROGEND, O_CREAT | O_EXCL, 0660, nitems);
    	if(shared.endprog == SEM_FAILED && errno == EEXIST ){
    		printf("delete existing semaphore endprog\n");
    		sem_unlink(SEM_PROGEND);
    		shared.endprog = sem_open(SEM_PROGEND, O_CREAT | O_EXCL, 0660, nitems);
    
    	} //if
    
    	for (i = 0; i < nitems; i++) {
    
    		sem_wait(shared.nstored);		/* wait for at least 1 stored item */
    		sem_wait(shared.mutex);
    
    		if (shared.buff[i % NBUFF] = i)
    			printf("buff[%d] = %d\n", i, shared.buff[i % NBUFF]);
    		sem_post(shared.mutex);
    		sem_post(shared.nempty);		/* 1 more empty slot */
    		
    	}
    	return 0;
    }
    https://stackoverflow.com/questions/32205396/share-posix-semaphore-among-multiple-processes
  • memory based semaphore, unix network programming p241

    이름있는 세마포어 말고 메모리에 올려 사용하는 방법도 있다. 책은 sem_init(…, 두번째 arg,…)에서 두번째 입력하는 숫자를 thread에서 공유할 거면 0, 프로세스간 할거면 1로 하라고 한다. 1로 하여 thread도 잘 된다.

    named semaphore는 포인터를 선언했고 파일에 영역을 만들었다. 이와 다르게 직접 데이터를 선언하고 주소로 넘겨줘야 한다.

    ipcs로 보일 법 한데, 안 보인다. 무엇이 잘못되었는지 모르겠다.

    /* include main */
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #define	NBUFF	 10
    #define	SEM_MUTEX	"mutex"	 	/* these are args to px_ipc_name() */
    #define	SEM_NEMPTY	"empty"
    #define	SEM_NSTORED	"nstored"
    
    int		nitems;					/* read-only by producer and consumer */
    struct {	/* data shared by producer and consumer */
      int	buff[NBUFF];
      //포인터 대신 세마포어로 변경.
      //sem_t	*mutex, *nempty, *nstored;
      sem_t	mutex, nempty, nstored;		/* semaphores, not pointers */
    
    } shared;
    
    void	*produce(void *), *consume(void *);
    
    int
    main(int argc, char **argv)
    {
    	pthread_t	tid_produce, tid_consume;
    
    	if (argc != 2)
    		perror("usage: prodcons1 <#items>");
    	nitems = atoi(argv[1]);
    		/* 4create three semaphores */
    	//memory based로 변경.
    	/*
    	shared.mutex = sem_open(SEM_MUTEX, O_CREAT | O_EXCL,
    							0660, 1);
    	shared.nempty = sem_open(SEM_NEMPTY, O_CREAT | O_EXCL,
    							 0660, NBUFF);
    	shared.nstored = sem_open(SEM_NSTORED, O_CREAT | O_EXCL,
    							  0660, 0);
    							  */
    
    
    	//두번째 파라미터를 0으로 설정해야 thread간 전달.
    	//sem_init(&shared.mutex, 1, 1) 설정해도 잘 됨..
    
    	sem_init(&shared.mutex, 0, 1);
    	sem_init(&shared.nempty, 0, NBUFF);
    	sem_init(&shared.nstored, 0, 0);
    
    
    		/* 4create one producer thread and one consumer thread */
    	//pthread_setconcurrency(2);
    	//pthread_setconcurrency();
    	pthread_create(&tid_produce, NULL, produce, NULL);
    	pthread_create(&tid_consume, NULL, consume, NULL);
    
    		/* 4wait for the two threads */
    	pthread_join(tid_produce, NULL);
    	pthread_join(tid_consume, NULL);
    
    		/* 4remove the semaphores */
    	//메모리 베이스로 변경.
    	/*
    	sem_unlink(SEM_MUTEX);
    	sem_unlink(SEM_NEMPTY);
    	sem_unlink(SEM_NSTORED);
    	*/
    
    
    	//ipcs로 확인하기위해 대기
    	sleep(10);
    
    	sem_destroy(&shared.mutex);
    	sem_destroy(&shared.nempty);
    	sem_destroy(&shared.nstored);
    
    	exit(0);
    }
    /* end main */
    
    /* include prodcons */
    void *
    produce(void *arg)
    {
    	int		i;
    
    	for (i = 0; i < nitems; i++) {
    
    		sem_wait(&shared.nempty);	/* wait for at least 1 empty slot */
    		sem_wait(&shared.mutex);
    
    		shared.buff[i % NBUFF] = i;	/* store i into circular buffer */
    		sem_post(&shared.mutex);
    		sem_post(&shared.nstored);	/* 1 more stored item */
    
    
    	}
    	return(NULL);
    }
    
    void *
    consume(void *arg)
    {
    	int		i;
    	int tmpnempty, tmpmutex, tmpnstored;
    
    	for (i = 0; i < nitems; i++) {
    
    
    		sem_wait(&shared.nstored);		/* wait for at least 1 stored item */
    		sem_wait(&shared.mutex);
    
    
    		if (shared.buff[i % NBUFF] = i)
    			printf("buff[%d] = %d\n", i, shared.buff[i % NBUFF]);
    		sem_post(&shared.mutex);
    		sem_post(&shared.nempty);		/* 1 more empty slot */
    
    	}
    	return(NULL);
    }
    /* end prodcons */
    
    pi@raspberrypi:~/Project/cCode/IPC $ ipcs
    
    ------ Message Queues --------
    key        msqid      owner      perms      used-bytes   messages    
    
    ------ Shared Memory Segments --------
    key        shmid      owner      perms      bytes      nattch     status      
    
    ------ Semaphore Arrays --------
    key        semid      owner      perms      nsems     
    
    

    ipcs는 system V 기능이라 posix semaphore는 해당하지 않는다. 보이지 않음이 당연하다.

  • semaphore p223 ~ p238

    name semaphore는 /dev/shm에 저장된다. 이름을 엄한 /tmp/xxx 이런 식으로 만들면 세마포어를 만들 수 없다. segment error로 죽는다. 책에서는 /tmp/로 넣어도 잘 동작해서 확인하는데 오래 걸렸다.

    디버그 하다 중간에 멈추면 /dev/shm에 sem*로 파일을 지울 수 없어 다음 실행에 세마포어를 받을 수 없다. 처음 시작 전 자기 이름으로 된 세마포어 있으면 지워야 한다.

    thread를 돌리면 미친 race condition이 피곤하게 한다. 참 헷갈리는데, 자주보면 익숙해 지겠지. thread를 돌리면 순서는 이제 별 의미 없는 듯 하다. sem_post하는 즉시 자기 thread를 실행하는게 아니라 다른 thread로 가서 프로그램을 실행한다. wait로 thread 이후 행을 잘 막는 게 핵심인 듯 하다.

    /* include main */
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <sys/stat.h>
    #define	NBUFF	 10
    #define	SEM_MUTEX	"mutex"	 	/* these are args to px_ipc_name() */
    #define	SEM_NEMPTY	"empty"
    #define	SEM_NSTORED	"nstored"
    
    int		nitems;					/* read-only by producer and consumer */
    struct {	/* data shared by producer and consumer */
      int	buff[NBUFF];
      sem_t	*mutex, *nempty, *nstored;
    } shared;
    
    void	*produce(void *), *consume(void *);
    
    int
    main(int argc, char **argv)
    {
    	pthread_t	tid_produce, tid_consume;
    	int errno;
    	
    
    	if (argc != 2)
    		perror("usage: prodcons1 <#items>");
    	nitems = atoi(argv[1]);
    		/* 4create three semaphores */
    	shared.mutex = sem_open(SEM_MUTEX, O_CREAT | O_EXCL,
    							0660, 1);
    	shared.nempty = sem_open(SEM_NEMPTY, O_CREAT | O_EXCL,
    							 0660, NBUFF);
    	shared.nstored = sem_open(SEM_NSTORED, O_CREAT | O_EXCL,
    							  0660, 0);
    
    		/* 4create one producer thread and one consumer thread */
    	//pthread_setconcurrency(2);
    	//pthread_setconcurrency();
    	pthread_create(&tid_produce, NULL, produce, NULL);
    	pthread_create(&tid_consume, NULL, consume, NULL);
    
    		/* 4wait for the two threads */
    	pthread_join(tid_produce, NULL);
    	pthread_join(tid_consume, NULL);
    
    		/* 4remove the semaphores */
    	sem_unlink(SEM_MUTEX);
    	sem_unlink(SEM_NEMPTY);
    	sem_unlink(SEM_NSTORED);
    	exit(0);
    }
    /* end main */
    
    /* include prodcons */
    void *
    produce(void *arg)
    {
    	int		i;
    	int tmpnempty, tmpmutex, tmpnstored;
    
    	for (i = 0; i < nitems; i++) {
    
    
    		//value check
    		//sem_getvalue(shared.nempty, &tmpnempty);
    		//sem_getvalue(shared.nstored, &tmpnstored);
    		//sem_getvalue(shared.mutex, &tmpmutex);
    
    		sem_wait(shared.nempty);	/* wait for at least 1 empty slot */
    		sem_wait(shared.mutex);
    
    		//value check
    		//sem_getvalue(shared.nempty, &tmpnempty);
    		//sem_getvalue(shared.nstored, &tmpnstored);
    		//sem_getvalue(shared.mutex, &tmpmutex);
    
    
    
    		shared.buff[i % NBUFF] = i;	/* store i into circular buffer */
    		sem_post(shared.mutex);
    		sem_post(shared.nstored);	/* 1 more stored item */
    		//value check
    		//sem_getvalue(shared.nempty, &tmpnempty);
    		//sem_getvalue(shared.nstored, &tmpnstored);
    		//sem_getvalue(shared.mutex, &tmpmutex);
    
    
    	}
    	return(NULL);
    }
    
    void *
    consume(void *arg)
    {
    	int		i;
    	int tmpnempty, tmpmutex, tmpnstored;
    
    	for (i = 0; i < nitems; i++) {
    		//value check
    		//sem_getvalue(shared.nempty, &tmpnempty);
    		//sem_getvalue(shared.mutex, &tmpmutex);
    		//sem_getvalue(shared.nstored, &tmpnstored);
    
    
    		sem_wait(shared.nstored);		/* wait for at least 1 stored item */
    		sem_wait(shared.mutex);
    		//value check
    		//sem_getvalue(shared.nempty, &tmpnempty);
    		//sem_getvalue(shared.mutex, &tmpmutex);
    		//sem_getvalue(shared.nstored, &tmpnstored);
    
    
    		if (shared.buff[i % NBUFF] = i)
    			printf("buff[%d] = %d\n", i, shared.buff[i % NBUFF]);
    		sem_post(shared.mutex);
    		sem_post(shared.nempty);		/* 1 more empty slot */
    		//value check
    		//sem_getvalue(shared.nempty, &tmpnempty);
    		//sem_getvalue(shared.mutex, &tmpmutex);
    		//sem_getvalue(shared.nstored, &tmpnstored);
    
    
    	}
    	return(NULL);
    }
    /* end prodcons */
    
    pi@raspberrypi:~/Project/cCode/IPC $ gdb --args ./a.out  3
    GNU gdb (Raspbian 8.2.1-2) 8.2.1
    Copyright (C) 2018 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    Type "show copying" and "show warranty" for details.
    This GDB was configured as "arm-linux-gnueabihf".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
        <http://www.gnu.org/software/gdb/documentation/>.
    
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from ./a.out...done.
    ...
    
    (gdb) info b
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x000107b4 in produce at semaphore.c:72
    	breakpoint already hit 3 times
    2       breakpoint     keep y   0x00010884 in consume at semaphore.c:108
    	breakpoint already hit 3 times
    (gdb) r
    Starting program: /home/pi/Project/cCode/IPC/a.out 3
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
    [New Thread 0xb6e31460 (LWP 2842)]
    [New Thread 0xb6630460 (LWP 2843)]
    [Switching to Thread 0xb6e31460 (LWP 2842)]
    
    Thread 2 "a.out" hit Breakpoint 1, produce (arg=0x0) at semaphore.c:72
    72			sem_wait(shared.nempty);	/* wait for at least 1 empty slot */
    1: shared = {buff = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, mutex = 0xb6ff8000, 
      nempty = 0xb6ff7000, nstored = 0xb6ff6000}
    2: *shared.nempty = {
      __size = "\024\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 20}
    3: *shared.nstored = {
      __size = "\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 0}
    4: *shared.mutex = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    (gdb) c
    Continuing.
    [Switching to Thread 0xb6630460 (LWP 2843)]
    
    Thread 3 "a.out" hit Breakpoint 2, consume (arg=0x0) at semaphore.c:108
    108			sem_wait(shared.nstored);		/* wait for at least 1 stored item */
    1: shared = {buff = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, mutex = 0xb6ff8000, 
      nempty = 0xb6ff7000, nstored = 0xb6ff6000}
    2: *shared.nempty = {
      __size = "\024\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 20}
    3: *shared.nstored = {
      __size = "\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 0}
    4: *shared.mutex = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    (gdb) c
    Continuing.
    [Switching to Thread 0xb6e31460 (LWP 2842)]
    
    Thread 2 "a.out" hit Breakpoint 1, produce (arg=0x0) at semaphore.c:72
    72			sem_wait(shared.nempty);	/* wait for at least 1 empty slot */
    1: shared = {buff = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, mutex = 0xb6ff8000, 
      nempty = 0xb6ff7000, nstored = 0xb6ff6000}
    2: *shared.nempty = {
      __size = "\022\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 18}
    3: *shared.nstored = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    4: *shared.mutex = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    (gdb) c
    Continuing.
    [Switching to Thread 0xb6630460 (LWP 2843)]
    
    Thread 3 "a.out" hit Breakpoint 2, consume (arg=0x0) at semaphore.c:108
    108			sem_wait(shared.nstored);		/* wait for at least 1 stored item */
    1: shared = {buff = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, mutex = 0xb6ff8000, 
      nempty = 0xb6ff7000, nstored = 0xb6ff6000}
    2: *shared.nempty = {
      __size = "\022\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 18}
    3: *shared.nstored = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    4: *shared.mutex = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    (gdb) c
    Continuing.
    [Switching to Thread 0xb6e31460 (LWP 2842)]
    
    Thread 2 "a.out" hit Breakpoint 1, produce (arg=0x0) at semaphore.c:72
    72			sem_wait(shared.nempty);	/* wait for at least 1 empty slot */
    1: shared = {buff = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, mutex = 0xb6ff8000, 
      nempty = 0xb6ff7000, nstored = 0xb6ff6000}
    2: *shared.nempty = {
      __size = "\022\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 18}
    3: *shared.nstored = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    4: *shared.mutex = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    (gdb) c
    Continuing.
    buff[1] = 1
    [Thread 0xb6e31460 (LWP 2842) exited]
    [Switching to Thread 0xb6630460 (LWP 2843)]
    
    Thread 3 "a.out" hit Breakpoint 2, consume (arg=0x0) at semaphore.c:108
    108			sem_wait(shared.nstored);		/* wait for at least 1 stored item */
    1: shared = {buff = {0, 1, 2, 0, 0, 0, 0, 0, 0, 0}, mutex = 0xb6ff8000, 
      nempty = 0xb6ff7000, nstored = 0xb6ff6000}
    2: *shared.nempty = {
      __size = "\022\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 18}
    3: *shared.nstored = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    4: *shared.mutex = {
      __size = "\002\000\000\000\200\000\000\000\000\000\000\000\000\000\000", 
      __align = 2}
    (gdb) c
    Continuing.
    buff[2] = 2
    [Thread 0xb6ffa070 (LWP 2841) exited]
    [Inferior 1 (process 2841) exited normally]
    (gdb) 
    
    https://unix.stackexchange.com/questions/275650/where-is-a-named-semaphore-stored