2013-08-24 22:55:05
标签:
IPC
1
2
3
4
5
6
7
8
|
#ifndef SEMUN_H_
#define SEMUN_H_
union
semun{
int
val;
struct
semid_ds * buf;
unsigned
short
* array;
};
#endif /* SEMUN_H_ */
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/sem.h>
#include "semun.h"
static
int
set_semvalue(
void
);
static
void
del_semvalue(
void
);
static
int
semaphore_p(
void
);
static
int
semaphore_v(
void
);
static
int
sem_id;
int
main(
int
argc,
char
**argv) {
int
i;
int
pause_time;
char
op_char =
'O'
;
srand
((unsigned
int
) getpid());
sem_id = semget((key_t) 1234, 1, 0666 | IPC_CREAT);
if
(argc > 1) {
if
(!set_semvalue()) {
perror
(
"Failed to initiallize semaphore\n"
);
exit
(1);
}
op_char =
'X'
;
sleep(2);
}
/*
*接下来是一个循环,它进入和离开临界区10次。在每次循环的开始,首先调用semaphore_p函数,它在
*程序将进入临界区时设置信号量以等待进入
*/
for
(i = 0; i < 10; i++) {
if
(!semaphore_p())
exit
(1);
printf
(
"%c"
, op_char);
fflush
(stdout);
pause_time =
rand
() % 3;
sleep(pause_time);
printf
(
"%c"
, op_char);
fflush
(stdout);
/*
* 在临界区之后,调用semaphore_v来将信号量设置为可用,然后等待一段随机的时间,再进入下一次循环
* 。在整个循环语句执行完毕后,调用del_semvalue函数来清理代码:
*/
if
(!semaphore_v())
exit
(1);
pause_time =
rand
() % 2;
sleep(pause_time);
}
printf
(
"n%d - finished\n"
, getpid());
if
(argc > 1) {
sleep(10);
del_semvalue();
}
exit
(0);
}
/*
* 函数set_semvalue通过将semctl调用的command参数设置为SETVAL来初始化信号量。
* 在使用信号量之前必须要这样做:
* */
static
int
set_semvalue()
{
union
semun sem_union;
sem_union.val=1;
if
(semctl(sem_id,0,SETVAL,sem_union)==-1)
{
return
0;
}
return
1;
}
/*
* 函数del_semvalue的形式与上面的函数几乎一样,
* 只不过它通过将semctl调用的command设置为IPC_RMID来删除信号量ID:
* */
static
void
del_semvalue()
{
union
semun sem_union;
if
(semctl(sem_id,0,IPC_RMID,sem_union)==-1)
{
perror
(
"Failed to delete semaphore\n"
);
}
}
//semaphore_p对信号量做减1操作
static
int
semaphore_p()
{
struct
sembuf sem_b;
sem_b.sem_num=0;
sem_b.sem_op=-1;
sem_b.sem_flg=SEM_UNDO;
if
(semop(sem_id,&sem_b,1)==-1)
{
perror
(
"semaphore_p failed"
);
return
0;
}
return
1;
}
//semaphore_p对信号量做加1操作
static
int
semaphore_v()
{
struct
sembuf sem_b;
sem_b.sem_num=0;
sem_b.sem_op=1;
sem_b.sem_flg=SEM_UNDO;
if
(semop(sem_id,&sem_b,1)==-1)
{
perror
(
"semaphore_v failed"
);
return
0;
}
return
1;
}
|
1
2
3
|
[root@localhost linux_C]
# ./sem1
OOXXOOXXOOXXOOXXOOXXOOXXOOXXOOXXOOXXOOn2182 - finished
X[root@localhost linux_C]
# Xn2181 - finished
|
1
2
3
4
5
6
7
8
|
#ifndef SHM_COM_H_
#define SHM_COM_H_
#define TEXT_SZ 2048
struct
shared_use_st{
int
written_by_you;
char
some_text[TEXT_SZ];
};
#endif /* SHM_COM_H_ */
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include "shm_com.h"
int
main(
int
argc,
char
**argv) {
int
running=1;
void
* shared_memory=NULL;
struct
shared_use_st * shared_stuff;
int
shmid;
srand
((unsigned
int
)getpid());
shmid=shmget((key_t)1234,
sizeof
(
struct
shared_use_st),0666|IPC_CREAT);
if
(shmid==-1)
{
perror
(
"shmget failed"
);
exit
(1);
}
/*
* (3)让程序可以访问这个共享内存
* */
shared_memory=shmat(shmid,NULL,0);
if
(shared_memory==(
void
*)-1)
{
perror
(
"shmat failed"
);
exit
(1);
}
printf
(
"Memory attached at %X\n"
,(
int
)shared_memory);
/*
* (4)程序的下一部分将shared_memory分配给shared_stuff,然后它输出written_by_you中
* 的文本。循环将一直执行到在written_by_you中找到end字符串为止。sleep调用强迫消费者程序
* 在临界区域多待一会儿,让生产者程序等待:
* */
shared_stuff=(
struct
shared_use_st *)shared_memory;
shared_stuff->written_by_you=0;
while
(running)
{
if
(shared_stuff->written_by_you)
{
printf
(
"You wrote:%s"
,shared_stuff->some_text);
sleep(
rand
()%4);
shared_stuff->written_by_you=0;
if
(
strncmp
(shared_stuff->some_text,
"end"
,3)==0)
{
running=0;
}
}
}
/*
* 最后,共享内存被分离,然后被删除:
* */
if
(shmdt(shared_memory)==-1)
{
perror
(
"shmdt failed"
);
exit
(1);
}
if
(shmctl(shmid,IPC_RMID,0)==-1)
{
perror
(
"shmctl failed"
);
exit
(1);
}
exit
(0);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include "shm_com.h"
int
main(
int
argc,
char
**argv) {
int
running=1;
void
* shared_memory=NULL;
struct
shared_use_st * shared_stuff;
char
buffer[BUFSIZ];
int
shmid;
shmid=shmget((key_t)1234,
sizeof
(
struct
shared_use_st),0666|IPC_CREAT);
if
(shmid==-1)
{
perror
(
"shmget failed"
);
exit
(1);
}
shared_memory=shmat(shmid,NULL,0);
if
(shared_memory==(
void
*)-1)
{
perror
(
"shmat failed"
);
exit
(1);
}
printf
(
"Memory attached at %X\n"
,(
int
)shared_memory);
shared_stuff=(
struct
shared_use_st *)shared_memory;
while
(running)
{
while
(shared_stuff->written_by_you==1)
{
sleep(1);
printf
(
"waiting for client...\n"
);
}
printf
(
"Enter some text:"
);
fgets
(buffer,BUFSIZ,stdin);
strncpy
(shared_stuff->some_text,buffer,TEXT_SZ);
shared_stuff->written_by_you=1;
if
(
strncmp
(buffer,
"end"
,3)==0)
{
running=0;
}
}
if
(shmdt(shared_memory)==-1)
{
perror
(
"shmdt failed"
);
exit
(1);
}
exit
(0);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[root@localhost linux_C]
# ./shm1 &
[7] 14327
[root@localhost linux_C]
# Memory attached at 5B0B7000
.
/shm2
Memory attached at 77C19000
Enter some text:yao
You wrote:yao
waiting
for
client...
waiting
for
client...
Enter some text:xia
You wrote:xia
waiting
for
client...
waiting
for
client...
waiting
for
client...
Enter some text:end
You wrote:end
[7]+ Done .
/shm1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
struct
my_msg_st {
long
int
my_msg_type;
char
some_text[BUFSIZ];
};
int
main(
int
argc,
char
**argv) {
int
running = 1;
int
msgid;
struct
my_msg_st some_data;
long
int
msg_to_receive = 0;
//首先建立消息队列
msgid = msgget((key_t) 1234, 0666 | IPC_CREAT);
if
(msgid == -1) {
perror
(
"msgget failed"
);
exit
(1);
}
//然后从队列中获取消息,直到遇见end消息为止。最后,删除消息队列:
while
(running) {
if
(msgrcv(msgid, (
void
*) &some_data, BUFSIZ, msg_to_receive, 0)
== -1) {
perror
(
"msgrcv failed"
);
exit
(1);
}
printf
(
"You wrote:%s"
, some_data.some_text);
if
(
strncmp
(some_data.some_text,
"end"
, 3) == 0) {
running = 0;
}
}
if
(msgctl(msgid, IPC_RMID, 0) == -1) {
perror
(
"msgctl failed"
);
exit
(1);
}
exit
(0);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/msg.h>
#define MAX_TEXT 512
struct
my_msg_st{
long
int
my_msg_type;
char
some_text[MAX_TEXT];
};
int
main(
int
argc,
char
**argv) {
int
running=1;
struct
my_msg_st some_data;
int
msgid;
char
buffer[BUFSIZ];
msgid=msgget((key_t)1234,0666|IPC_CREAT);
if
(msgid==-1)
{
perror
(
"msgget failed"
);
exit
(1);
}
while
(running)
{
printf
(
"Enter some text:"
);
fgets
(buffer,BUFSIZ,stdin);
some_data.my_msg_type=1;
strcpy
(some_data.some_text,buffer);
if
(msgsnd(msgid,(
void
*)&some_data,MAX_TEXT,0)==-1)
{
perror
(
"msgsnd failed"
);
exit
(1);
}
if
(
strncmp
(buffer,
"end"
,3)==0)
{
running=0;
}
}
exit
(0);
}
|
1
2
3
4
5
6
7
8
|
[root@localhost linux_C]
# ./msg2
Enter some text:yao
Enter some text:xia
Enter some text:end
[root@localhost linux_C]
# ./msg1
You wrote:yao
You wrote:hesdf
You wrote:end
|