Linux程序设计入门Word格式.docx

上传人:b****7 文档编号:22834488 上传时间:2023-02-05 格式:DOCX 页数:20 大小:22.93KB
下载 相关 举报
Linux程序设计入门Word格式.docx_第1页
第1页 / 共20页
Linux程序设计入门Word格式.docx_第2页
第2页 / 共20页
Linux程序设计入门Word格式.docx_第3页
第3页 / 共20页
Linux程序设计入门Word格式.docx_第4页
第4页 / 共20页
Linux程序设计入门Word格式.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

Linux程序设计入门Word格式.docx

《Linux程序设计入门Word格式.docx》由会员分享,可在线阅读,更多相关《Linux程序设计入门Word格式.docx(20页珍藏版)》请在冰豆网上搜索。

Linux程序设计入门Word格式.docx

intsem_getvalue(sem_t*sem);

sem_init创建一个信号灯,并初始化其值为value.pshared决定了信号量能否在几个进程

间共享.由于目前Linux还没有实现进程间共享信号灯,所以这个值只能够取0.sem_dest

roy是用来删除信号灯的.sem_wait调用将阻塞进程,直到信号灯的值大于0.这个函数返回

的时候自动的将信号灯的值的件一.sem_post和sem_wait相反,是将信号灯的内容加一同

时发出信号唤醒等待的进程..sem_trywait和sem_wait相同,不过不阻塞的,当信号灯的值

为0的时候返回EAGAIN,表示以后重试.sem_getvalue得到信号灯的值.

由于Linux不支持,我们没有办法用源程序解释了.

这几个函数的使用相当简单的.比如我们有一个程序要向一个系统打印机打印两页.我们

首先创建一个信号灯,并使其初始值为1,表示我们有一个资源可用.然后一个进程调用se

m_wait由于这个时候信号灯的值为1,所以这个函数返回,打印机开始打印了,同时信号灯

的值为0了.如果第二个进程要打印,调用sem_wait时候,由于信号灯的值为0,资源不可

用,于是被阻塞了.当第一个进程打印完成以后,调用sem_post信号灯的值为1了,这个时候

系统通知第二个进程,于是第二个进程的sem_wait返回.第二个进程开始打印了.

不过我们可以使用线程来解决这个问题的.我们会在后面解释什么是线程的.编译包含上

面这几个函数的程序要加上-lrt选贤,以连接librt.so库

2。

SystemV信号量为了解决上面哪个问题,我们也可以使用SystemV信号量.很幸运的

是Linux实现了SystemV信号量.这样我们就可以用实例来解释了.SystemV信号量的函

数主要有下面几个.

sys/types.h>

sys/ipc.h>

sys/sem.h>

key_tftok(char*pathname,charproj);

intsemget(key_tkey,intnsems,intsemflg);

intsemctl(intsemid,intsemnum,intcmd,unionsemunarg);

intsemop(intsemid,structsembuf*spos,intnspos);

structsembuf{

shortsem_num;

/*使用那一个信号*/

shortsem_op;

/*进行什么操作*/

shortsem_flg;

/*操作的标志*/

};

ftok函数是根据pathname和proj来创建一个关键字.semget创建一个信号量.成功时返回

信号的ID,key是一个关键字,可以是用ftok创建的也可以是IPC_PRIVATE表明由系统选用

一个关键字.nsems表明我们创建的信号个数.semflg是创建的权限标志,和我们创建一个

文件的标志相同.

semctl对信号量进行一系列的控制.semid是要操作的信号标志,semnum是信号的个数,cm

d是操作的命令.经常用的两个值是:

SETVAL(设置信号量的值)和IPC_RMID(删除信号灯).

arg是一个给cmd的参数.

semop是对信号进行操作的函数.semid是信号标志,spos是一个操作数组表明要进行什么

操作,nspos表明数组的个数.如果sem_op大于0,那么操作将sem_op加入到信号量的值中

并唤醒等待信号增加的进程.如果为0,当信号量的值是0的时候,函数返回,否则阻塞直

到信号量的值为0.如果小于0,函数判断信号量的值加上这个负值.如果结果为0唤醒等待

信号量为0的进程,如果小与0函数阻塞.如果大于0,那么从信号量里面减去这个值并返回

..

下面我们一以一个实例来说明这几个函数的使用方法.这个程序用标准错误输出来代替我

们用的打印机.

stdio.h>

unistd.h>

limits.h>

errno.h>

string.h>

stdlib.h>

sys/stat.h>

sys/wait.h>

#definePERMSS_IRUSR|S_IWUSR

voidinit_semaphore_struct(structsembuf*sem,intsemnum,

intsemop,intsemflg)

{

/*初始话信号灯结构*/

sem->

sem_num=semnum;

sem_op=semop;

sem_flg=semflg;

}

intdel_semaphore(intsemid)

/*信号灯并不随程序的结束而被删除,如果我们没删除的话(将1改为0)

可以用ipcs命令查看到信号灯,用ipcrm可以删除信号灯的

*/

#if1

returnsemctl(semid,0,IPC_RMID);

#endif

intmain(intargc,char**argv)

charbuffer[MAX_CANON],*c;

inti,n;

intsemid,semop_ret,status;

pid_tchildpid;

structsembufsemwait,semsignal;

if((argc!

=2)||((n=atoi(argv[1]))<

1))

fprintf(stderr,"

Usage:

%snumber\n\a"

argv[0]);

exit

(1);

/*使用IPC_PRIVATE表示由系统选择一个关键字来创建*/

/*创建以后信号灯的初始值为0*/

if((semid=semget(IPC_PRIVATE,1,PERMS))==-1)

[%d]:

AcessSemaphoreError:

%s\n\a"

getpid(),strerror(errno));

/*semwait是要求资源的操作(-1)*/

init_semaphore_struct(&

semwait,0,-1,0);

/*semsignal是释放资源的操作(+1)*/

semsignal,0,1,0);

/*开始的时候有一个系统资源(一个标准错误输出)*/

if(semop(semid,&

semsignal,1)==-1)

IncrementSemaphoreError:

if(del_semaphore(semid)==-1)

DestroySemaphoreError:

/*创建一个进程链*/

for(i=0;

i<

n;

i++)

if(childpid=fork())break;

sprintf(buffer,"

[i=%d]-->

[Process=%d]-->

[Parent=%d]-->

[Child=%d]\n"

i,getpid(),getppid(),childpid);

c=buffer;

/*这里要求资源,进入原子操作*/

while(((semop_ret=semop(semid,&

semwait,1))==-1)&

&

(errno==EINTR));

if(semop_ret==-1)

DecrementSemaphoreError:

else

while(*c!

='

'

)fputc(*c++,stderr);

/*原子操作完成,赶快释放资源*/

semsignal,1))==-1)&

/*不能够在其他进程反问信号灯的时候,我们删除了信号灯*/

while((wait(&

status)==-1)&

/*信号灯只能够被删除一次的*/

if(i==1)

exit(0);

信号灯的主要用途是保护临界资源(在一个时刻只被一个进程所拥有).

3。

SystemV消息队列为了便于进程之间通信,我们可以使用管道通信SystemV也提供了

一些函数来实现进程的通信.这就是消息队列.

sys/msg.h>

intmsgget(key_tkey,intmsgflg);

intmsgsnd(intmsgid,structmsgbuf*msgp,intmsgsz,intmsgflg);

intmsgrcv(intmsgid,structmsgbuf*msgp,intmsgsz,

longmsgtype,intmsgflg);

intmsgctl(Intmsgid,intcmd,structmsqid_ds*buf);

structmsgbuf{

longmsgtype;

/*消息类型*/

......./*其他数据类型*/

msgget函数和semget一样,返回一个消息队列的标志.msgctl和semctl是对消息进行控制

..msgsnd和msgrcv函数是用来进行消息通讯的.msgid是接受或者发送的消息队列标志.

msgp是接受或者发送的内容.msgsz是消息的大小.结构msgbuf包含的内容是至少有一个

为msgtype.其他的成分是用户定义的.对于发送函数msgflg指出缓冲区用完时候的操作.

接受函数指出无消息时候的处理.一般为0.接收函数msgtype指出接收消息时候的操作.

如果msgtype=0,接收消息队列的第一个消息.大于0接收队列中消息类型等于这个值的第

一个消息.小于0接收消息队列中小于或者等于msgtype绝对值的所有消息中的最小一个消

息.我们以一个实例来解释进程通信.下面这个程序有server和client组成.先运行服务

端后运行客户端.

服务端server.c

#defineMSG_FILE"

server.c"

#defineBUFFER255

#definePERMS_IRUSR|S_IWUSR

structmsgtype{

longmtype;

charbuffer[BUFFER+1];

intmain()

structmsgtypemsg;

key_tkey;

intmsgid;

if((key=ftok(MSG_FILE,'

a'

))==-1)

CreatKeyError:

%s\a\n"

strerror(errno));

if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)

CreatMessageError:

while

(1)

msgrcv(msgid,&

msg,sizeof(structmsgtype),1,0);

ServerReceive:

%s\n"

msg.buffer);

msg.mtype=2;

msgsnd(msgid,&

msg,sizeof(structmsgtype),0);

----------------------------------------------------------------------------

----

客户端(client.c)

if(argc!

=2)

%sstring\n\a"

if((msgid=msgget(key,PERM))==-1)

msg.mtype=1;

strncpy(msg.buffer,argv[1],BUFFER);

memset(&

msg,'

sizeof(structmsgtype));

msg,sizeof(structmsgtype),2,0);

Clientreceive:

注意服务端创建的消息队列最后没有删除,我们要使用ipcrm命令来删除的.

4。

SystemV共享内存还有一个进程通信的方法是使用共享内存.SystemV提供了以下几个

函数以实现共享内存.

sys/shm.h>

intshmget(key_tkey,intsize,intshmflg);

void*shmat(intshmid,constvoid*shmaddr,intshmflg);

intshmdt(constvoid*shmaddr);

intshmctl(intshmid,intcmd,structshmid_ds*buf);

shmget和shmctl没有什么好解释的.size是共享内存的大小.shmat是用来连接共享内存

的.shmdt是用来断开共享内存的.不要被共享内存词语吓倒,共享内存其实很容易实现和

使用的.shmaddr,shmflg我们只要用0代替就可以了.在使用一个共享内存之前我们调用s

hmat得到共享内存的开始地址,使用结束以后我们使用shmdt断开这个内存.

intshmid;

char*p_addr,*c_addr;

if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1)

CreateShareMemoryError:

if(fork())

p_addr=shmat(shmid,0,0);

memset(p_addr,'

1024);

strncpy(p_addr,argv[1],1024);

c_addr=shmat(shmid,0,0);

printf("

Clientget%s"

c_addr);

这个程序是父进程将参数写入到共享内存,然后子进程把内容读出来.最后我们要使用ip

crm释放资源的.先用ipcs找出ID然后用ipcrmshmID删除.

后记:

进程通信(IPC)是网络程序的基础,在很多的网络程序当中会大量的使用进程通信的概念

和知识.其实进程通信是一件非常复杂的事情,我在这里只是简单的介绍了一下.如果你想

学习进程通信的详细知识,最好的办法是自己不断的写程序和看联机手册.现在网络上有

了很多的知识可以去参考.可惜我看到的很多都是英文编写的.如果你找到了有中文的版

本请尽快告诉我.谢谢!

7)Linux程序设计入门--线程操作

Linux下线程的创建

介绍在Linux下线程的创建和基本的使用.Linux下的线程是一个非常复杂的问题,由

于我对线程的学习不时很好,我在这里只是简单的介绍线程的创建和基本的使用,关于线

程的高级使用(如线程的属性,线程的互斥,线程的同步等等问题)可以参考我后面给出的

资料.现在关于线程的资料在网络上可以找到许多英文资料,后面我罗列了许多链接,对

线程的高级属性感兴趣的话可以参考一下.等到我对线程的了解比较深刻的时候,我回来

完成这篇文章.如果您对线程了解的详尽我也非常高兴能够由您来完善.

先介绍什么是线程.我们编写的程序大多数可以看成是单线程的.就是程序是按照一定的

顺序来执行.如果我们使用线程的话,程序就会在我们创建线成的地方分叉,变成两个"

序"

在执行.粗略的看来好象和子进程差不多的,其实不然.子进程是通过拷贝父进程的地

址空间来执行的.而线程是通过共享程序代码来执行的,讲的通俗一点就是线程的相同的

代码会被执行几次.使用线程的好处是可以节省资源,由于线程是通过共享代码的,所以没

有进程调度那么复杂.

线程的创建和使用

线程的创建是用下面的几个函数来实现的.

pthread.h>

intpthread_create(pthread_t*thread,pthread_attr_t*attr,

void*(*start_

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 演讲主持

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1