2006-1-12 进程通信已经学习完了!
时间:2006-01-12 来源:晏东
2006年1月12日星期四 阴见多云
i. 系统调用int semctl(int semid, int nsems, int cmd, union semun semops);操作函数
示例:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define SEM_RESOURCE_MAX 5 /* Initial value of all semaphores */
union semun{
struct semid_ds *buf;
int val;
unsigned short int *array;
struct seminfo *__buf;
};
key_t key = IPC_PRIVATE;
static int sem_creat(int nsems);
static int sem_rm(int semid);
static int sem_get(int semid, union semun semops);
static int sem_setmode(int semid, char *mode);
int main()
{
int semid;
union semun semops;
struct semid_ds mysemds;
semops.buf = &mysemds;
semid = sem_creat(10);
sem_setmode(semid, "0777");
sem_rm(semid);
exit(0);
}
static int sem_creat(int nsems)
{
int semid;
if ((semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0660)) == -1)
{
perror("semget error");
return -1;
}
union semun semops;
semops.val = SEM_RESOURCE_MAX;
for (int i =0; i<nsems; i++)
{
semctl(semid, nsems, SETVAL, semops);
}
return semid;
}
static int sem_rm(int semid)
{
if (semctl(semid, 0, IPC_RMID, 0) == -1)
{
perror("semrm error");
return -1;
}
return 0;
}
static int sem_get(int semid, union semun semops)
{
//union sumun 结构必须指定其到底用什么变量。
// struct semid_ds mysemds;
// semops.buf = &mysemds;
if (semctl(semid, 0, IPC_STAT, semops) == -1)
{
perror("sem_get error");
return -1;
}
return 0;
}
static int sem_setmode(int semid, char *mode)
{
union semun opts;
struct semid_ds mysemds;
opts.buf = &mysemds;
sem_get(semid, opts);
sscanf(mode, "%ho", &opts.buf->sem_perm.mode);
if (semctl(semid, 0, IPC_SET, opts) == -1)
{
perror("IPC_SET error");
return -1;
}
return 0;
}
b) 共享内存
i. 共享内存数据结构shmid_ds
/* One shmid data structure for each shared memory segment in the system. */
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
time_t shm_atime; /* last attach time */
time_t shm_dtime; /* last detach time */
time_t shm_ctime; /* last change time */
unsigned short shm_cpid; /* pid of creator */
unsigned short shm_lpid; /* pid of last operator */
short shm_nattch; /* no. of current attaches */
/* the following are private */
unsigned short shm_npages; /* size of segment (pages) */
unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
struct vm_area_struct *attaches; /* descriptors for attaches */
};
shm_perm 是数据结构i p c _ p e r m的一个实例。这里保存的是内存段的存取权限,和其他的
有关内存段创建者的信息。
shm_segsz 内存段的字节大小。
shm_atime 最后一个进程存取内存段的时间。
shm_dtime 最后一个进程离开内存段的时间。
shm_ctime 内存段最后改动的时间。
shm_cpid 内存段创建进程的P I D。
shm_lpid 最后一个使用内存段的进程的P I D。
shm_nattch 当前使用内存段的进程总数
ii. 系统调用shmget(key_t key, int size, int flag);
生成或取一个共享内存段,flag同前,注意IPC_CREAT和IPC_EXCL.
iii. 返回共享内存段连接到进程的地址shmat
void *shmat(int shmid, const void *addr, int flag);
成功返回地址,错误返回-1,并生成errno;
其中addr可以人工指定,但最好使用0(自动寻找没有分配的地址)
iv. 系统调用,操作函数shmctl(int shmid, int cmd, sturct shmid_ds *buf);
成功返回0,错误返回-1,并生成errno;
CMD:
IPC_STAT : 取shmid_ds 结构存放在buf中;
IPC_SET :设置shmid_ds结构;
IPC_RMID:删除该共享内存段;
v. 将共享内存段从进程地址中移走shmdt
void shmdt()或
int shmdt(const void *addr);
错误返回-1,并生成errno;
QT:还是没整起,郁闷啊!晚上回去争取整出来!