操作系统实验教程(7)

2018-12-17 15:09

附:msgid_ds结构定义如下: struct msgid_ds

{struct ipc_perm msg_perm; /*许可权结构*/ shot padl[7]; /*由系统使用*/ ushort onsg_qnum; /*队列上消息数*/ ushort msg_qbytes; /*队列上最大字节数*/ ushort msg_lspid; ushort msg_lrpid;

/*最后发送消息的PID*/ /*最后接收消息的PID*/ /*最后发送消息的时间*/ /*最后接收消息的时间*/

time_t msg__stime; time_t msg_rtime; me_t msg_ctime; };

struct ipc_perm {ushort uid;

/*最后更改时间*/

/*当前用户id*/ /*当前进程组id*/ /*创建用户id*/ /*创建进程组id*/ /*存取许可权*/

ushort gid;

ushort cuid;

ushort cgid ushort mode;

{shot patl;long pad2} /*由系统使用*/ };

例:使用系统调用msgget( ), msgsnd( ), msgrcv( )及msgctl()编制一长度为1K

的消息发送和接收的程序 。

(1)为了便于操作和观察结果,用一个程序为“引子”,先后fork( )两个子进程,SERVER和CLIENT,进行通信。

(2)SERVER端建立一个Key为75的消息队列,等待其他进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER 。SERVER每接收到一个消息后显示一句“(server)received”。

(3)CLIENT端使用Key为75的消息队列,先后发送类型从10到1的消息,然后退出。最后的一个消息,既是 SERVER端需要的结束信号。CLIENT每发

29

送一条消息后显示一句“(client)sent”。

(4)父进程在 SERVER和 CLIENT均退出后结束。 参考程序:

#include #include #include #include

#define MSGKEY 75 /*定义关键词MEGKEY*/ struct msgform /*消息结构*/ { long mtype; char mtxt[1030]; /*文本长度*/ }msg;

int msgqid,i;

void CLIENT( ) { int i; msgqid=msgget(MSGKEY,0777); for(i=10;i>=1;i--) { msg.mtype=i; printf(\ msgsnd(msgqid,&msg,1024,0); /*发送消息msg入msgid消息队列*/ } exit(0); }

void SERVER( ) {

msgqid=msgget(MSGKEY,0777|IPC_CREAT); /*由关键字获得消息队列*/ do { msgrcv(msgqid,&msg,1030,0,0); /*从队列msgid接受消息msg*/ printf(\

}while(msg.mtype!=1); /*消息类型为1时,释放队列*/ msgctl(msgqid, IPC_RMID,0); exit(0); }

main() {

if(fork()) SERVER();

30

}

else CLIENT( ); wait(0); wait(0);

<结果>

从理想的结果来说,应当是每当Client发送一个消息后,server接收该消息,Client再发送下一条。也就是说“(Client)sent”和“(server)received”的字样应该在屏幕上交替出现。实际的结果大多是,先由 Client 发送两条消息,然后Server接收一条消息。此后Client、Server交替发送和接收消息,最后一次接收两条消息,Client 和Server 分别发送和接收了10条消息,与预期设想一致。 <分析>

message的传送和控制并不保证完全同步,当一个程序不再激活状态的时候,它完全可能继续睡眠,造成上面现象,在多次send message 后才 receive message.这一点有助于理解消息转送的实现机理。

实验五 Linux下多线程编程

5.1 linux多线程编程常用函数 1.创建缺省线程

int pthread_create(pthread_t *thread,pthread_attr_t *attr, void*(*start_routine), void *arg); 参数:

? thread 线程标识符 ? attr 线程属性设置

? start_routine 线程函数起始地址 ? arg 传递给start_routine的参数

当pthread_create() 成功时,所创建线程的ID 被存储在由thread指向的位置中。第二个参数用于设置线程属性,如果不需要特殊的属性,可以简单的设置该参数为NULL,最后两个参数告诉线程将要启动执行的函数和传递给该函数的参数。调用成功完成后返回0,其他的值都表示出现错误。 2.终止线程

31

一个线程的结束有两种途径,一种是线程函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit实现 。

void pthread_exit (void *__retval)

唯一的参数是函数的返回代码 。如果pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给 thread_return。

一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。 3. 等待线程终止用(等待一个线程的结束)

int pthread_join(thread_t tid, void **status); 参数:

第一个参数为被等待的线程标识符 。

第二个参数为一个用户定义的指针,用来存储被等待线程返回值。 这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。 返回值:

调用成功完成后,pthread_join() 将返回0。其他任何返回值都表示出现了错误。

4、线程标识符pthread_t

pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义: typedef unsigned long int pthread_t; ? 用来标识一个线程 5、线程属性pthread_attr_t

使用pthread_create函数创建线程时,线程参数一般都为默认值,即将第二个参数设为NULL ,对大多数程序来说,使用默认属性就够了。

属性结构为pthread_attr_t,它在头文件/usr/include/pthread.h中定义,属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。

32

5.2 多线程示例

? 编写Linux下的多线程程序,需要使用头文件pthread.h ? 多线程程序实例1

/* example.c*/ #include #include void *thread(void) {

int i;

for(i=0;i<3;i++)

printf(\}

int main(void) {

pthread_t id; int ret;

ret=pthread_create(&id,NULL,thread,NULL); if (ret!=0){

printf (\ exit (1); }

int i;

for (i=0;i<3;i++)

printf (\ pthread_join(id, NULL); return(0); }

执行:gcc example.c -lpthread -o example 或者:gcc -g -c example.c

gcc example.o -lpthread -o example

运行example1,我们得到如下结果: This is the main process. This is a pthread. This is the main process. This is the main process. This is a pthread. This is a pthread.

33


操作系统实验教程(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:2013白蒲中学高一数学教案:函数:27

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: