Chinaunix首页 | 论坛 | 博客
  • 博客访问: 910832
  • 博文数量: 299
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2493
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-21 10:07
个人简介

Linux后台服务器编程。

文章分类

全部博文(299)

文章存档

2015年(2)

2014年(297)

分类: 网络与安全

2014-08-17 15:37:47

Linux高性能服务器编程


13 多进程编程
#include
#include
pid_t fork(void);


子进程的代码和父进程完全相同,同时它还会复制父进程的数据(堆栈数据和静态数据),数据的复制采用写时复制(copy on write);


父进程打开的文件描述符在子进程中也打开,且文件描述符引用计数加1.且父进程的用户根目录、当前工作目录等变量的引用计数均会加1.


在子进程中执行其他程序,即替换当前进程映像:
#include
extern char** environ;


int execl(const char* path, const char* arg, ...);
int execlp(const char* file, const char* arg, ...);
int execle(const char* path, const char* arg, ..., char* const envp[]);
int execv(const char* path, char* const argv[]);
int execvp(const char* file, char* const argv[]);
int execve(const char* path, char* const argv[], char* const envp[]);


exec函数不会关闭原程序打开的文件描述符,除非该文件描述符被设置了类似SOCK_CLOEXEC的属性。


#include
#include
pid_t wait(int* stat_loc);//将阻塞进程
pid_t waitpid(pid_t pid, int* stat_loc, int options);//可以设置WNOHANG参数


管道:父子间进程进行相互通信。
只能保证在一个方向上进行数据传输。
int pipefd[2];
pipe(pipefd);
//其中pipefd[0]读数据pipefd[1]写数据


socketpair();






struct ipc_perm{
key_t key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
};


信号量:pv操作
#include
int semget(key_t key, int num_sems, int sem_flags);


struct semid_ds{
struct ipc_perm sem_perm;
unsigned long int sem_nsems;
time_t sem_otime;
time_t sem_ctime;
};


关联的重要的内核变量:
unsigned short semval;
unsigned short semzcnt;
unsigned short semncnt;
pid_t sempid;


int semop(int sem_id, struct sembuf* sem_ops, size_t num_sem_ops);
struct sembuf{
unsigned short int sem_num;
short int sem_op;
short int sem_flg;
};


int semctl(int sem_id, int sem_num, int command, ...);
第四个参数推荐使用的格式:
union semun{
int val;
struct semid_ds* buf;
unsigned short* array;
struct seminfo* __buf;
};


struct seminfo{
int semmni;//最多包含的信号量集个数
int semmns;//最多包含的信号量个数
int semmsl;//一个信号量集最多允许包含的信号量数目
int semopm;//semop一次最多能执行的sem_op操作数目
int semusz;//sem_undo结构体的大小
int semvmx;//最大允许的信号量值
int semaem;//最多允许的UNDO次数
};


特殊键值IPC_PRIVATE
semget的调用者可以给其key参数传递一个特殊的键值IPC_PRIVATE(其值为0),这样无论该信号量是否已经存在,semget都将创建一个新的信号量。(更好的名字:IPC_NEW)




共享内存
#include
int shmget(key_t key, size_t size, int shmflg);
struct shmid_ds{
struct ipc_perm shm_perm;
size_t shm_segsz;//共享内存大小,单位字节
__time_t shm_atime;//最后一次调用shmat的时间
__time_t shm_dtime;
__time_t shm_ctime;
__pid_t shm_cpid;
__pid_t  shm_lpid;//最后一次执行shmat或shmdt操作的进程的pid
shmatt_t shm_nattach;//目前关联到此共享内存的进程数量
};


共享内存被创建/获取之后,我们不能立即访问它,而是需要先将它关联到进程的地址空间中。使用完共享内存之后,也需要将它从进程地址空间分离。
void* shmat(int shm_id, const void* shm_addr, int shmflg);
int shmdt(const void* shm_addr);


int shmctl(int shm_id, int command, struct shmid_ds* buf);


共享内存的POSIX方法:
利用mmap函数的MAP_ANONYMOUS标志我们可以实现父子进程间的匿名内存共享。通过打开同一个文件,mmap也可以实现无关进程之间的内存共享。linux提供了另外一种利用mmap在无关进程之间共享内存的方式。这种方式无须任何文件的支持,但需要如下函数创建或打开一个POSIX共享内存对象:
#include
#include
#include
int shm_open(const char* name, int oflag, mode_t mode);
shm_open的使用方法和open系统调用完全相同。


与打开文件最后需要关闭一样,由shm_open创建的共享内存对象使用完之后也需要被删除。这个过程通过如下函数实现:
int shm_unlink(const char* name);
该函数将name参数指定的共享内存对象标记为等待删除。当所有使用该共享内存对象的进程都使用ummap将它从进程中分离之后,系统将销毁这个共享内存对象所占据的资源。编译时需要指定链接选项-lrt。




消息队列:
#include
int msgget(key_t key, int msgflg);
struct msqid_ds{
struct ipc_perm msg_perm;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
unsigned long __msg_cbytes;//消息队列已有的字节数
msgqnum_t msg_qnum;//消息队列已有的消息数
msglen_t msg_qbytes;//消息队列允许的最大字节数
pid_t msg_lspid;
pid_t msg_lrpid;
};


int msgsnd(int msgqid, const void* msg_ptr, size_t msg_sz, int msgflg);
struct msgbuf{
long mtype;
char mtext[512];
};
支持IPC_NOWAIT参数


int msgrcv(int msqid, void* msg_ptr, size_t msg_sz, long int msgtype, int msgflg);


int msgctl(int msqid, int command, struct msqid_ds* buf);


阅读(1348) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~