操作系统上机实验报告-进程通信(消息,软中断,管道)进程管理(并发运行)
操作系统上机实验报告
实验1、【进程管理】父进程创建两个子进程,各自输出一个字符,通过多次运
行的结果分析进程并发运行的特点。
源代码,
#include
main()
{
int p1,p2;
while((p1=fork())==-1);
if(p1==0)
putchar('b');
else
{
while((p2=fork())==-1);
if(p2==0)
putchar('c');
else
putchar('a');
}
}
运行结果,
bacswufe@linux:~> ./a
bcaswufe@linux:~> ./a
bcaswufe@linux:~> ./a
bcaswufe@linux:~> ./a
cabswufe@linux:~> ./a
bcaswufe@linux:~> ./a
bacswufe@linux:~> ./a
分析,多数结果为bca,偶尔有bac,cab出现。程序并发执行时依照时间片轮转,
父子进程执行时有一定的随机性,出现了不同结果。
实验2、【进程管理】父进程创建一个子进程,在父子进程中分别输出各自的进程标识号,分析运行结果。
源代码,
#include
main()
{
int p1,p2;
while((p1==fork())==-1);
if((p1=fork())==0)
{ printf("--------this is child process\n");
printf("--------my pid(child) is %d\n",getpid());
printf("--------my parent pid is %d\n",getppid());
}
else
{ printf("this is parent process\n");
printf("my pid(parent) is %d\n",getpid());
printf("my child pid is %d\n",p1);
}
}
运行结果,
swufe@linux:~> ./wsj
this is parent process
my pid(parent) is 8633
my child pid is 8636
--------this is child process
--------my pid(child) is 8635
--------my parent pid is 8634
swufe@linux:~> ./wsj
--------this is child process --------my pid(child) is 8630 --------my parent pid is 8627 this is parent process
my pid(parent) is 8627
my child pid is 8630
swufe@linux:~> ./wsj
--------this is child process --------my pid(child) is 8629 --------my parent pid is 8628 this is parent process
my pid(parent) is 8628
my child pid is 8629
swufe@linux:~> ./wsj
this is parent process
my pid(parent) is 8634
my child pid is 8635
--------this is child process --------my pid(child) is 8636 --------my parent pid is 1 分析,还是由于时间片轮转的关系,可能父进程先执行,或者子进程先执行。父进程先执行后会自动消除,此时其子进程托管给一号进程,即出现子进程输出“--------my parent pid is 1”的情况。
实验3、【进程通信—管道】创建管道,父进程与两个子进程通过管道传递数据。
源代码,
#include
#include
#include
#include
main()
{
int i,r,p1,p2,fd[2];
char buf[50],s[50];
pipe(fd);
while((p1=fork())==-1); if(p1==0)
{
lockf(fd[1],1,0);
sprintf(buf,"child process p1 is sending messages!\n");
printf("child process p1!\n");
write(fd[1],buf,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
else
{
while((p2=fork())==-1);
if (p2==0)
{
lockf(fd[1],1,0);
sprintf(buf,"child process p2 is sending messages\n");
printf("child process p2!\n");
write(fd[1],buf,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
wait(0);
if(r=read(fd[0],s,50)==-1) printf("can't read pipe\n");
else printf("%s\n",s);
wait(0);
if(r=read(fd[0],s,50)==-1) printf("can't read pipe\n");
else printf("%s\n",s);
exit(0);
}
}
实验结果,
swufe@linux:~> ./bbc
child process p1!
child process p2!
child process p1 is sending messages! child process p2 is sending messages 分析,第一个子进程锁定写入端,并将数据写入管道,并睡眠等待,解锁。随后第二个子进程执行第一个进程的操作。最后父进程的两个 wait()函数,读取子进程的数据,并将它显示出来。
实验4、【进程通信—软中断】不断输入字符串,把其中的小写字母转换为大写字母后输出,直到按键Ctrl,C、Ctrl,Z或Kill终止,并显示软中断信号的名称和编号,参考
课件
超市陈列培训课件免费下载搭石ppt课件免费下载公安保密教育课件下载病媒生物防治课件 可下载高中数学必修四课件打包下载
。
源代码,
#include
#include
#include
void stop();
main()
{
char str[10];
signal(SIGINT,&stop); for(;;)
{
printf("\ns=");
scanf("%s",str); if (strcmp(str,"ok")==0)
kill(getpid(),SIGINT); }
}
void stop(int signumber)
{
printf("\n process is killed by %d!\n\n",signumber);
exit(0);
}
运行结果,
s=43t
s=fdgd
s=ok
process is killed by 2!
s=
process is killed by 2!
分析,第一个结果的前两次输入都未成功,因为设定的中断字符为“ok”,第三次由设定的输入ok而中断,并且显示中断命令的软中断号为2,第二个结果中断为在键盘上输入“ctrl+c”命令,效果等同于输入“ok”字符。软中断的发送与接受是可以分开的,在死循环中发送软中断信号仍旧可以被循环外的软中断处理语句捕捉。
实验5、【进程通信—软中断】不断输入字符串,当输入为“intermit”、 “stop、” “quit”时,向自身发软中断信号SIGINT、SIGTSTP、SIGTERM,退出执行,参考课
件。
源代码,
#include
#include
#include
void terminate(int signumber);
main(void)
{
char buf[100];
int i;
signal(SIGINT,&terminate);
signal(SIGTSTP,&terminate);
signal(SIGTERM,&terminate);
printf("\nPid of this process :%d.\n\n",getpid());
for(;;)
{
printf("Input is :");
scanf("%s",buf);
if(strcmp(buf,"intermit")==0)
kill(getpid(),SIGINT);
else if(strcmp(buf,"stop")==0)
raise(SIGTSTP);
else if(strcmp(buf,"quit")==0)
raise(SIGTERM);
else
printf("Your input is :%s\n\n",buf);
}
return 0;
}
void terminate(int signumber )
{
if (signumber==2)
printf("catch signal SIGNIT,signumber is %d\n\n",signumber);
else if (signumber==20)
printf("catch signal SIGTSTP,signumber is %d\n\n",signumber);
else if (signumber==15)
printf("catch signal SIGTERM,signumber is %d\n\n",signumber);
exit(0);
}
运行结果,
Pid of this process :8810.
Input is :54gte
Your input is : 54gte
Input is :quit
catch signal SIGTERM,signumber is 15
Pid of this process :8816
Input is :stop
catch signal SIGTSTP,signumber is 20
Pid of this process :8823
Input is :intermit
catch signal SIGNIT,signumber is 2
分析,首先输出执行程序的进程编号,进入死循环,输入一般字符串原样输出。
当输入intermit、quit等设定的字符时发送软中断信号,被循环外的软中断相应
语句捕捉,输出相应软中断代码后程序结束。
实验6、【进程通信—消息】创建三个子进程,其中两个调用client.c ,另一个调
用server.c,相互之间发送消息。
源代码,
client:
#include
#include
#include
#include
#include
#define MSGKEY 75
struct msgform
{
long mtype;
char mtext[256];
};
main (int argc, char *argv[]) {
struct msgform msg;
int msgqid,pid,*pint;
msgqid =msgget (MSGKEY,0777|IPC_CREAT);
printf("msgqid = %d\n\n",msgqid);
pid =getpid();
pint =(int*) msg.mtext;
*pint =pid;
msg.mtype =1;
msgsnd (msgqid,&msg,sizeof(int),0);
msgrcv(msgqid,&msg,256,pid,0);
pint =(int *)msg.mtext;
pid = (int) *pint;
printf("Client %s: receive from Server process %d|n ",argv[1],pid);
}
server:
#include #include #include #include
#include
#define MSGKEY 75
struct msgform
{
long mtype;
char mtext[256];
}msg;
int msgqid;
main ()
{
int i,pid,*pint;
extern cleanup ();
for (i =0;i<20; i++)
signal (i,cleanup);
msgqid =msgget (MSGKEY, 0777|IPC_CREAT);
for (;;)
{
msgrcv (msgqid,&msg,256,1,0);
pint = (int*) msg.mtext;
pid =*pint;
printf ("server: receive from pid %d\n",pid);
msg.mtype =pid ;
pint= (int*) msg.mtext;
*pint =getpid();
msgsnd (msgqid,&msg,sizeof (int ),0);
}
}
cleanup()
{
msgctl (msgqid ,IPC_RMID,0);
exit(0);
}
msg:
#include
#include
#include
#include
main()
{ int pid1,pid2,pid3;
pid1 = vfork();
if (pid1 == 0)
{ printf("\nClient1 process %4d :\n",getpid());
execlp("/home/swufe/client","client","1",NULL);
}
else
{ pid2 = vfork();
if (pid2 == 0)
{ printf("Client2 process %4d:\n",getpid());
execlp("/home/student/swufe","client","2",NULL);
}
else
{ pid3 = vfork();
if (pid3 == 0)
{ printf("Server3 process %4d:\n",getpid());
execlp("/home/swufe/server","server",NULL);
}
else
printf("\nThis is Parent process %4d ! \n",getpid());
}
}
wait(0);
wait(0);
wait(0);
}
运行结果,
Client1 process2211:
msgqid=360448
Client2 process 2212
msgqid=360448
Server3 process2213
This is Parant process2210!
server:receive from pid 2211
client 1 :receive from server process 2213
server:receive from pid 2911
client 2 :receive from server process 2210 分析,MSG程序分别调用Cilent与Server进行数据传递,显示Client1, Client2, Server3,父进程的进程编号,并且表明出Server3进程的信号源来自于Client1,同时表明Client1与Server3的联系。