实验二 进程和进程通信
1.自己设计一个程序,该程序创建一个子进程,使父子进程合作,协调地完成某一功能。
要求在该程序中还要使用进程的睡眠、进程图象改换、父进程等待子进程终止、信号的
设置与传送(包括信号处理程序)、子进程的终止等有关进程的系统调用。
2.分别利用 UNIX 的消息通信机制、共享内存机制(用信号灯实施进程间的同步和互斥)
实现两个进程间的数据通信。具体的通信数据可从一个文件读出,接收方进程可将收到
的数据写入一个新文件,以便能判断数据传送的正确性。
参考源代码 1:
main()
{
int
while ((i=fork( ))==-1);
if (i) {
i,pid,status = 1;
/* 父进程 */
printf (“It is the parent process.\n”);
pid =wait (&status);
printf (“Child process %d,status =%d \n”,pid,status);
} else {
/* 子进程 */
printf (“It is the child process.\n”);
execl (“/bin/ls”,”ls”,”-l”,(char*)0); /* 映像改换 */
printf (“execl
exit (2);
error.\n”);
/* 映像改换失败 */
}
printf (“Parent process finish. \n”);
}
参考源代码 2:
# include
# include
main ( )
{
int status;
pid_t pid;
void func ( );
signal (SIGUSR1,func);
if
(pid=fork () ) {
/* 预置信号处理程序 */
printf ("Parent: will send signal.\n");
kill (pid, SIGUSR1);
wait (& status);
printf ("status=%d: Parent finished:\n",status);
/* 发送信号 */
/* 等待子进程停止 */
} else {
sleep (10);
/* 等待接受信号 */
printf ("Child:signal is received.\n");
exit (0);
}
}
void func ()
{
printf ("It is signal processing function.\n");
}
参考源代码 3:
/* msgcom.h */
#include
#include
#include
#include
#define MSGKEY 5678
struct msgtype{
long mtype;
int text;
};
/* 请求进程 */
#include "msgcom.h"
main()
{
struct msgtype buf;
int qid,pid;
qid=msgget(MSGKEY,IPC_CREAT|0666);
buf.mtype=1;
buf.text=pid=getpid();
msgsnd(qid,&buf,sizeof(buf.text),0);
msgrcv(qid,&buf,512,pid,MSG_NOERROR);
printf("Request received a massags from server,
buf.mtype);
}
/* 服务器进程 */
#include "msgcom.h"
main()
{
struct msgtype buf;
int qid;
if((qid=msgget(MSGKEY,IPC_CREAT|0666))==-1)
type is:%d\n " ,
return(-1);
while(1){
msgrcv(qid,&buf,512,1,MSG_NOERROR);
printf("Server receive a request from
process %d\n",buf.text);
buf.mtype=buf.text;
msgsnd(qid,&buf,sizeof(int),0);
}
}
参考源代码 4:
#include
#include
#include
int creatsem(key)
key_t key;
{
/* 如 sem.h 中已定义,则省略 */
int sid;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} arg;
if((sid=semget(key,1,0666|IPC_CREAT))==-1)
syserr("semget");
arg.val=1;
if(semctl(sid,0,SETVAL,arg)==-1)
syserr("semctl");
return(sid);
}
void P(sid)
int sid;
{
static void semcall();
semcall(sid,-1);
}
void V(sid)
int sid;
{
static void semcall();
semcall(sid,1);
}
static void semcall(sid,op)
int sid,op;
{
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = op;
sb.sem_flg = 0;
if(semop(sid,&sb,1) == -1)
syserr("semop");
};
父进程一次读入一个字符串,将其存放在共享内存中,子进程从共享内存中取出数据,输出
打印。
#include
#include
#include
#include
#define SHMKEY 18001
#define SIZE 1024
#define SEMKEY1 19001
#define SEMKEY2 19002
extern int creatsem();
extern void P(),V(),syserr();
/* 共享内存关键字 */
/* 共享内存长度 */
/* 信号灯组 1 关键字 */
/* 信号灯组 2 关键字 */
main()
{
char *segaddr;
int segid,sid1,sid2;
/* 创建共享内存段 */
if((segid=shmget(SHMKEY,SIZE,
IPC_CREAT|0666))==-1)
syserr("shmget");
/* 将共享内存映射到进程数据空间 */
segaddr=shmat(segid,0,0);
sid1=creatsem(SEMKEY1); /* 创建两个信号灯,初值为 1 */
sid2=creatsem(SEMKEY2);
P(sid2);
/* 置信号灯 2 值为 0,表示缓冲区空 */
if(!fork())
while(1){
/* 子进程,接收和输出 */
P(sid2);
printf("Received from Parent: %s\n",
segaddr);
V(sid1);
}
while(1) {
/* 父进程,输入和存储 */
P(sid1);
scanf("%s",segaddr);
V(sid2);
}
}