上机1 Linux使用环境
一、上机目的
- 了解Linux的命令及使用格式。
- 熟悉 Linux的常用基本命令。
- 练习并掌握 Linux提供的 vi 编辑器来编辑 C 程序。
- 学会利用 gcc(cc)编译、调试 C 程序。
二、上机任务
- 参考实验指导书实验一部份,练习常用Linux命令的使用。
- 用 vi 编写一个简单的、显示"Hello,World!"的 C 程序,用 gcc 编译并观察编译后的结果,并运行生成的可执行文件。
三、源码及结果截图
3.1 Linux常用命令
上机2 进程管理
一、上机目的
1、掌握进程的概念,明确进程的含义。
2、认识并了解并发执行的实质。
3、掌握进程的创建方法。
二、上机任务
- 编写一段程序,使用系统调用 fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示’a’,子进程分别显示字符’b’和字符’c’。试观察记录屏幕上的显示结果,并分析原因。
- 修改上述程序,每一个进程循环显示一句话。子进程显示’daughter …‘及’son ……’,父进程显示 ‘parent ……’,观察结果,分析原因。
三、源码及结果截图
3.1 源码
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
void main()
{
int p1, p2, i;
while ((p1 = fork()) == -1);
if (p1 == 0)
{
for (i = 0; i < 10; i++)
printf("daughter %dn", i);
}
else
{
while ((p2 = fork()) == -1);
if (p2 == 0)
{
for (i = 0; i < 10; i++)
printf("son %din", i);
}
else
{
for (i = 0; i < 10; i++)
printf(" parent %dn", i);
}
}
}
3.2 运行结果
上机3 进程同步
一、上机目的
- 熟悉进程的睡眠、同步、撤消等进程控制方法。
- 分析进程竞争资源的现象,学习解决进程互斥的方法
二、上机任务
- 用 fork( )创建一个进程,再调用 exec( )用新的程序替换该子进程的内容,利用 wait( )来控制进程执行顺序,并分析其结果。
- 任务3中的程序,用 lockf( )来给每一个进程加锁,以实现进程之间的互斥,观察并分析出现的现象。
三、源码及结果截图
3.1 进程的控制实验
(1) 源码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/wait.h>
void main()
{
int pid;
pid = fork();
switch (pid)
{
case -1:
printf("fork fail!\n");
exit(-1);
case 0:
execl("/bin/ls", "ls", "-l", "-color", NULL);
printf("exec fail!\n");
exit(1);
default:
wait(NULL);
printf("ls completed!\n");
exit(0);
}
}
(2) 运行结果
3.2 进程的互斥实验
(1) 代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/wait.h>
void main()
{
int p1, p2, i;
while ((p1 = fork()) == -1);
if (p1 == 0)
{
// lockf(1,1,0);
for (i = 0; i < 5; i++) printf("daughter %d\n", i);
// lockf(1,0,0);
}
else
{
while ((p2 = fork()) == -1);
if (p2 == 0)
{
// lockf(1,1,0);
for (i = 0; i < 5; i++) printf("son %d\n", i);
// lockf(1,0,0);
}
else
{
// lockf(1,1,0);
for (i = 0; i < 5; i++) printf("parent %d\n", i);
// lockf(1,0,0);
}
}
}
(2) 运行结果
上锁时:
未上锁时:
上机4 进程通信——软中断通信
一、上机目的
1.了解什么是信号,并熟悉进程之间软中断通信的基本原理。
二、上机任务
- 编写程序:用 fork( )创建两个子进程,再用系统调用 signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键);捕捉到中断信号后,父进程用系统调用 kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:
Child process1 is killed by parent!
Child process2 is killed by parent!
父进程等待两个子进程终止后,输出如下的信息后终止:
Parent process is killed!
分析利用软中断通信实现进程同步的机理。
三、源码及结果截图
(1) 源码
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void waiting(),stop(),stop2();
int wait_mark;
int main()
{
int p1,p2,stdout;
while((p1=fork())==-1);
if(p1>0){
while((p2=fork())==-1);
if(p2>0)
{
wait_mark = 1;
signal(SIGINT,stop);
waiting();
kill(p1,16);
kill(p2,17);
wait(0);
wait(0);
printf("Parent process is killed!\n");
exit(0);
}
else
{
wait_mark = 1;
signal(17,stop);
waiting();
lockf(stdout,1,0);
printf("Child process 2 is killed by parent!\n");
lockf(stdout,0,0);
exit(0);
}
}
else
{
wait_mark=1;
signal(16,stop);
waiting();
lockf(stdout,1,0);
printf("Child process 1 is killed by parent!\n");
lockf(stdout,0,0);
exit(0);
}
}
void waiting()
{
while(wait_mark!=0);
}
void stop()
{
wait_mark=0;
}
(2) 运行结果
上机5 进程通信——管道通信
一、上机目的
- 了解什么是管道,并熟悉管道通信方式。
二、上机任务
- 编写程序实现进程的管道通信。用系统调用 pipe( )建立一管道,两个子进程 P1 和 P2分别向管道各写一句话:
Child 1 is sending a message!
Child 2 is sending a message!
父进程从管道中读出两个来自子进程的信息并显示。
三、源码及结果截图
(1) 源码
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int pid1,pid2;
int main()
{
int fd[2];
char outpipe[100],inpipe[100];
pipe(fd);
while((pid1=fork())==-1);
if(pid1==0)
{
lockf(fd[1],1,0);
sprintf(outpipe,"child 1 process is sending message!");
write(fd[1],outpipe,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
else
{
while((pid2=fork())==-1);
if(pid2==0)
{
lockf(fd[1],1,0);
sprintf(outpipe,"child 2 process is sending message!");
write(fd[1],outpipe,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
else
{
wait(0);
read(fd[0],inpipe,50);
printf("%s \n",inpipe);
wait(0);
read(fd[0],inpipe,50);
printf("%s \n",inpipe);
exit(0);
}
}
}
(2) 运行结果
上机6 进程通信——消息和共享存储区通信
一、上机目的
- 了解什么是消息,并熟悉消息传送机制。
- 了解什么是共享存储区,并熟悉共享存储区通信机制。
二、上机任务
- 定义适当的消息结构,并利用msgget创建(打开)消息队列,让通信进程使用msgsnd、msgrev进行消息的收发,通信结束后使用msgctl删除消息队列。
- 使用shmget创建一个1KB的共享存储区,之后利用shmat让通信进程附接到共享存储区,以通过对共享存储区的读写来实现进程通信,通信结束之后利用shmdt断开连接并使用shmctl删除共享存储区。
三、源码及结果截图
3.1 第一问
(1) 源码
// client.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
#include<stdlib.h>
#define MSGKEY 75
struct msgform
{
long mtype;
char mtext[10];
}msg;
int msgqid;
void client()
{
int i;
msgqid = msgget(MSGKEY,0777);
for(i=10;i>=1;i--)
{
msg.mtype=i;
printf("(client)sent\n");
msgsnd(msgqid,&msg,4,0);
}
exit(0);
}
int main()
{
client();
}
//server.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
#include<stdlib.h>
#define MSGKEY 75
struct msgform
{
long mtype;
char mtext[1000];
}msg;
int msgqid;
void server()
{
msgqid = msgget(MSGKEY,0777|IPC_CREAT);
do
{
msgrcv(msgqid,&msg,1030,0,0);
printf("(server)received\n");
}while(msg.mtype!=1);
msgctl(msgqid,IPC_RMID,0);
exit(0);
}
void main()
{
server();
}
(2) 运行结果
3.2 第二问
(1) 源码
#include<sys/types.h>
#include <sys/wait.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include <stdlib.h>
#include <unistd.h>
#include<stdio.h>
#define SHMKEY 75
int shmid,i;
int *addr;
void client()
{
int i;
shmid = shmget(SHMKEY,1024,0777);
addr = shmat(shmid,0,0);
for(i=5;i>=0;i--)
{
while(*addr!=-1);
printf("(client)sent\n");
*addr = i;
}
exit(0);
}
void server()
{
shmid = shmget(SHMKEY,1024,0777|IPC_CREAT);
addr = shmat(shmid,0,0);
do
{
*addr = -1;
while(*addr==-1);
printf("(server)received\n");
}while(*addr);
shmctl(shmid,IPC_RMID,0);
exit(0);
}
void main()
{
while((i=fork())==-1);
if(!i) server();
system("ipcs -m");
while((i=fork())==-1);
if(!i) client();
wait(0);
wait(0);
}