多进程 linux,linux 多进程知识

进程是针对系统而不是用户的,对于用户而言,其面对的是程序,当用户输入指令执行一个程序的时候,对系统而言它将启动一个进程,但是和系统不同的是,在这个进程中,系统可能需要再启动一个或者多个进程来完成独立的多个任务,多进程编程主要包括进程控制和进程间通信。

linux环境下进程结构:

linux进程在内存中有三部分数据:代码段 数据段和堆栈段,在CPU都有上述三种段寄存器,以方便操作系统运行

代码段:存放程序源代码,多个进程运行相同的程序,他们就使用相同的代码段

堆栈段:存放子程序的返回地址 子程序的参数以及程序的局部变量

数据段:存放程序的全局变量 常数以及动态数据分配的数据空间

linux下的多进程编程包括进程控制和进程间通信,下面详细介绍:

linxu下的进程控制:

传统的linux环境下,有两个基本的操作用于创建和修改进程:fork()函数用来创建一个新的进程,该进程几乎是当前进程的一个完全拷贝;exec()函数族用来启动另外的进程代替当前的进程。

fork()函数

例子:

void main(){

for(;;)

fork();

}

该进程也不做就是一直循环的fork,结果是不断的产生进程,而这些进程又不断产生新的进程,系统满的时候就瘫痪了。所以系统管理员可以预先指定每个用户最多运行的最大进程数,只要运行者不是root权限就没问题。

exec()函数族

该函数族用来在一个进程中启动另一个程序的执行,一个进程一旦调用了exec函数族,它本身就死亡了,系统把原来进程的代码段替换成程序的代码,废弃原有的数据段和堆栈段,使用新程序的数据段和堆栈段,唯一留下的就是进程号,对于系统来说,还是同一个进程,但是已经是另一个程序了。

如果程序想启动一个新的程序但是不结束自己,那样的话就得用fork和exec函数族配合使用了。

linux下的进程间通信:

首先进程间通信至少可以通过传送文件来实现,不同的进程通过一个或者多个文件来传递信息,在很多应用程序中都使用了这个方法,不过这种方式比较低级,很简单!

linux系统中实现进程间通信的方式很多,常用的有:管道 消息队列 共享内存 信号量 套接口等。

管道:

管道是进程间通信的最古老的方式,分两种:有名管道和无名管道。父进程和子进程间通信使用无名管道,同一机器上的任意两个进程间的通信使用有名管道。

无名管道:

无名管道由函数pipe()来创建  int pipe(int filedis[2]) 参数filedis返回两个文件的描述符号:filedis[0]为读而打开 filedis[1]为写而打开 filedis[1]的输出是filedis[0]的输入

例子:

#define INPUT 0

#define OUTPUT 1

void main(){

int file_descri[2];

pid_t pid;

char buf[256];

int return_count;

pipe(file_descri);//创建了无名管道

pid=fork();

if(-1==pid){

printf("ERROE in fork\n");

exit(1)

}

else if(0==pid){

printf("child process\n");

close(file_descri[INPUT]);

write(file_descri[OUTPUT],"www.jiaojiaoni.com",strlen("www.jiaojiaoni.com"));

exit(0);

}

else{

printf("Parent process!\n");

close(file_descri[OUTPUT]);

return_count=read(file_descri[INPUT],buf,sizeof[buf]);

printf("%d bytes of data,the data is %s \n",return_count,buf);

}

}

有名管道

(有名管道就是有名字的管道):

linux系统下的有名管道由两种方式创建:命令行方式mknod和函数mkfifo

方式一: mkfifo("myfifo","rw")

方式二: mknod myfifo p

上述两种方式都在当前目录下生成了一个名为fifo的有名管道。

生成了有名管道后就可以使用一般的文件io函数如open close read和writre对其进行操作了

例子:(假如我们已经有了一个名为myfifo的有名管道)

//进程一 读有名管道

void main(){

FILE* infile;

int count=1;

char buf[80];

infile=fopen("myfifo","r");

if(NULL==infile){

printf("ERROR in fopen!\n");

exit(1);

}

count=fread(buf,1,80,infile);

while(count>0)

printf("receive from pipe:%s\n",buf);

fclose(infile1);

}

//进程二 写有名管道

void main(){

FILE* outfile;

int count=1;

char buf[80];

outfile=fopen("myfifo","w");

if(NULL==out_file){

printf("ERROR open!\n");

exit(1);

}

sprintf(buf,"hello everyone my website is www.jiaojiaoni.com\n");

fwrite(buf,1,80,outfile);

fclose(outfile);

}

共享内存

共享内存是运行在同一机器上的进程间的通信最快的方式,因为数据直接存在内存不需要在不同的进程间进行复制,通常由一个进程创建一个共享内存区,其余进程对这块内存进行读写。

得到共享内存有两种方式:映射/dev/mem设备和内存映像文件

映射/dev/mem不给系统带来额外的开销,但是在实际中应用不常用,因为它控制存取的是实际的物理内存,在linux系统下,只有通过限制linux系统存取的内存才可以做到

通常常用的方式是使用shmXXX函数族来实现共享内存进行存储

int shmget(key_t key,int size,int flag) 获得一个共享存储标识符,也就是请求分配size大小的内存用作共享内存  key_t关键字用来存储引用标识符,是个长整型数据,在头文件sys/types.h中定义

上述函数执行完毕,共享内存就创建完毕了,其余进程使用 shmat()函数就可以连接到自身的地址空间中了

void* shmat(int shmid,void* addr,int flag)

shmid为shmget函数返回的共享存储标识符

addr和flag决定了以什么方式来确定连接地址

函数的返回值就是该进程数据段所连接的实际地址,也就是共享内存的地址,进程可以对其进行读写操作

使用共享存储来实现进程间的通信的注意点是对数据存取的同步,必须确保一个进程去读取数据时,它所想要的数据已经写好了,通常信号量可以被用来实现对共享存储数据存取的同步

信号量从本质上说是一个计数器,用来计算对某个资源的存取情况,在这里可以用于同步的实现。

套接字

套接字是实现linux操作系统和其他操作系统之间的进程间通信的方式之一,www ftp telnet等服务都是基于套接字的

除了适用于异地的计算机进程间通信外,套接字同样适用于本地同一计算机内部的进程间通信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值