任务1:
要求:编写程序task71.c实现进程的管道通信。父进程创建两个子进程,父子进程通过管道来传送数据。两个子进程P1和P2分别向管道各写一句话:
Child P1 is sending My name <您的姓名XXX>!
Child P2 is sending the current time <当前系统时间,包括年月日时分秒>!
父进程从管道中读出两个来自子进程的信息并显示。
提示:获取系统时间的函数是”time_t time(time_t *t);”,将time_t格式时间转换成字符串格式的函数是”char *ctime(const time_t *timep);”
设计思想:
通过管道重定向来实现进程之间的信息交流,父进程使用FOR循环来读取2次数据。
#include "wrapper.h"
int main()
{
int fds[2];
int pid11, pid12;
char buf[1024];
char cpid1[] = "Child P1 is sending My name 泠霖凛!";
char cpid2[80];
struct tm *newtime;
time_t t = time(NULL);
newtime = localtime(&t);
strftime(cpid2, 100, "Child P2 is sending<%Y年%m月%d日%H时%M分%S秒>", newtime);
pipe(fds);
pid11 = fork();
if (pid11 == 0)
{
close(fds[0]);
write(fds[1], cpid1, strlen(cpid1));
close(fds[1]);
dup2(4, 0);
exit(0);
}
else
{
pid12 = fork();
if (pid12 == 0)
{
close(fds[0]);
write(fds[1], cpid2, strlen(cpid2));
close(fds[1]);
dup2(4, 0);
exit(0);
}
else
{
for (int i = 0; i < 2; i++)
{
dup(0);
close(0);
dup(fds[0]);
read(fds[0], buf, 1024);
printf("\b%s\n", buf);
close(fds[0]);
close(fds[1]);
}
}
}
}
任务2:
要求:编写消息队列通信程序task72s.c和task72c.c,利用消息队列通信实现一个简单的客户/服务器应用,多个客户进程task72c可并发地向服务器进程发送消息,服务器task72s向每个客户发送消息接收回执。比如进程PID为1234的客户端发送的消息为”hello from Process 1234”,服务器收到该消息后发回消息为“receipt of hello from <您的姓名xxx>’s server to Process 1234”
设计思想:
使用消息队列来传递信息,消息队列的信息是存放在系统里的,每个消息的值需要确定类型,不然会传递失败;要注意服务器会和客户端冲突抢信息,因此服务器发送信息后需要睡眠1秒来规避冲突。
task72s.c:
#include "wrapper.h"
char *mygetpid(char *str);
char *getfirst(char *str);
typedef struct MESSAGE
{
long mtype;
char mtext[512];
} mymsg, *pmymsg;
int main(int argc, char *argv[])
{
int rtn;
int msqid;
key_t key;
mymsg msginfo;
char first[512];
char buf[512];
if (argc != 2)
{
fprintf(stderr, "请以./task72s<key>的形式运行给出的消息队列键值\n");
exit(0);
}
sscanf(argv[1], "%x", &key);
msqid = msgget(key, 0644);
msginfo.mtype = 1;
while (1)
{
memset(msginfo.mtext, 0, sizeof(msginfo.mtext));
rtn = msgrcv(msqid, (pmymsg)&msginfo, sizeof(msginfo.mtext), 1, 0);
if (rtn == -1)
continue;
strcpy(first, msginfo.mtext);
printf("收到消息:%s\n", first);
strcat(buf, "receipt of ");
strcat(buf, getfirst(msginfo.mtext));
strcat(buf, " from 泠霖凛's server to Process ");
strcat(buf, mygetpid(first));
strcpy(msginfo.mtext, buf);
rtn = msgsnd(msqid, &msginfo, strlen(msginfo.mtext), 0);
sleep(1);
memset(buf, 0, sizeof(buf));
if (strcmp(first, "close") == 0)
{
return 0;
}
}
}
//服务端提取消息对应的线程
char *mygetpid(char *str)
{
char *p[21];
memcpy(p, str, 4);
char *t;
p[0] = strtok(str, " ");
int i = 0;
while (p[i] != NULL)
{
i++;
p[i] = strtok(NULL, " ");
}
t = p[i - 1];
return t;
}
char *getfirst(char *str)
{
char *p[21];
memcpy(p, str, 4);
char *t;
p[0] = strtok(str, " ");
t = p[0];
return t;
}
task72c.c:
#include "wrapper.h"
typedef struct MESSAGE
{
long mtype;
char mtext[512];
} mymsg, *pmymsg;
char mbuf[1024];
int main(int argc, char *argv[])
{
int rtn;
int msqid;
key_t key;
int mypid = (int)(getpid());
char cpid[10];
sprintf(cpid, "%d", mypid);
if (argc != 3)
{
fprintf(stderr, "程序启动方式为./task72c<消息队列键值><待发送消息>\n");
exit(0);
}
sscanf(argv[1], "%x", &key);
msqid = msgget(key, 0644);
mymsg msg;
msg.mtype = 1;
strcat(argv[2], " from Process ");
strcat(argv[2], cpid);
strcpy(msg.mtext, argv[2]);
rtn = msgsnd(msqid, &msg, strlen(msg.mtext), 0);
printf("you send a message \"%s\" to msq %d\n", argv[1], msqid);
memset(msg.mtext, 0, sizeof(msg.mtext));
rtn = msgrcv(msqid, (pmymsg)&msg, sizeof(msg.mtext), 1, 0);
printf("%s\n", msg.mtext);
return 0;
}
任务3:
要求:编写程序task73.c,父进程创建两个子进程P1和P2,P1通过共享内存将1、2、3、…、10依次发送给进程P2输出显示,每次发送一个,父子进程间利用IPC信号量同步。
设计思想:
使用共享内存来实现进程P1与P2之间的交流,使用IPC信号量来实现进程之间的同步互斥。
#include "wrapper.h"
int main(int argc, char *argv[])
{
int sig = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
} arg_sem;
arg_sem.val = 1;
semctl(sig, 0, SETVAL, arg_sem);
struct sembuf sem, fsem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
fsem.sem_num = 0;
fsem.sem_op = 1;
fsem.sem_flg = SEM_UNDO;
int pid11, pid12;
int rtn;
int shmid;
char buf[2];
key_t key;
void *shmptr;
if (argc <= 1)
{
fprintf(stderr, "请以./task73<key>的形式运行,给出消息队列的键值\n");
exit(1);
}
sscanf(argv[1], "%x", &key);
shmid = shmget(key, 4096, IPC_CREAT | 0644);
pid11 = fork();
if (pid11 == 0)
{
for (int i = 1; i <= 10; i++)
{
semop(sig, &sem, 1);
shmptr = shmat(shmid, 0, 0);
sprintf(buf, "%d", i);
memcpy(shmptr, buf, strlen(buf));
shmdt(shmptr);
semop(sig, &fsem, 1);
}
}
else
{
pid12 = fork();
if (pid12 == 0)
{
for (int i = 1; i <= 10; i++)
{
semop(sig, &sem, 1);
shmptr = shmat(shmid, 0, 0);
printf("%s\n", (char *)shmptr);
shmdt(shmptr);
semop(sig, &fsem, 1);
}
}
else
{
sleep(1);
exit(0);
}
}
}