shm_open()
使用shm_open来操作共享内存
要点一定要用ftruncate把文件大小于设置为共享内存大小
shm_open () 创建并打开一个新的或打开一个现有的 POSIX 共享内存对象。POSIX 共享内存对象实际上是一个句柄,不相关的进程可以使用它来mmap()共享内存的同一区域。shm_unlink () 函数执行相反的 操作,删除之前由shm_open () 创建的对象。
#define SHARED_OBJ_NAME "/somename"
int shmFd = shm_open(SHARED_OBJ_NAME, O_RDWR, S_IRUSR | S_IWUSR);
ftruncate(shmFd, sizeof(msg));
...
operations
...
close(shmFd);
...
shm_unlink(SHARED_OBJ_NAME);
return 0;
mmap()
mmap() 系统调用能够将文件映射到内存空间,然后可以通过读写内存来读写文件。我们先来看看 mmap() 系统调用的用法吧,mmap() 函数的原型如下:
start:指定要映射的内存地址,一般设置为 NULL 让操作系统自动选择合适的内存地址。
length:映射地址空间的字节数,它从被映射文件开头 offset 个字节开始算起。
prot:指定共享内存的访问权限。可取如下几个值的可选:PROT_READ(可读), PROT_WRITE(可写), PROT_EXEC(可执行), PROT_NONE(不可访问)。
flags:由以下几个常值指定:MAP_SHARED(共享的) MAP_PRIVATE(私有的), MAP_FIXED(表示必须使用 start 参数作为开始地址,如果失败不进行修正),其中,MAP_SHARED , MAP_PRIVATE必选其一,而 MAP_FIXED 则不推荐使用。
fd:表示要映射的文件句柄。
offset:表示映射文件的偏移量,一般设置为 0 表示从文件头部开始映射。
函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
munmap()
int munmap(void *addr, size_t length);
取消内存映射,addr是由mmap成功返回的地址,length是要取消的内存长度,munmap 只是将映射的内存从进程的地址空间撤销,如果不调用这个函数,则在进程终止前,该片区域将得不到释放。
mkfifo()
int mkfifo(const char * pathname,mode_t mode);
mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此 umask值也会影响到FIFO文件的权限。Mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式存取。当使用open()来打开 FIFO文件时,O_NONBLOCK旗标会有影响
1、当使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。
2、没有使用O_NONBLOCK 旗标时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。
返回值
若成功则返回0,否则返回-1,错误原因存于errno中。
错误代码
EACCESS 参数pathname所指定的目录路径无可执行的权限
EEXIST 参数pathname所指定的文件已存在。
ENAMETOOLONG 参数pathname的路径名称太长。
ENOENT 参数pathname包含的目录不存在
ENOSPC 文件系统的剩余空间不足
ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。
EROFS 参数pathname指定的文件存在于只读文件系统内。
使用方法:
#define NAMED_PIPE "/var/lock/pipename"
...
{
int ret = mkfifo(NAMED_PIPE, 0666);
if (ret < 0)
printf("Error when creating FIFO. %s\n", strerror(errno));
message msg;
int fd = open(NAMED_PIPE, O_WRONLY); //
ret = write(fd, &msg, sizeof(msg));
if (ret < 0)
printf("Process %d: Error while writing message. %s\n", pid, strerror(errno));
close(fd);
unlink(NAMED_PIPE);
return 0;
}
waitpid() & wait()
#include "csapp.h"
constexpr int N = 2;
signed main(void) {
int status, i;
pid_t pid[N], retpid;
for (int i = 0;i < N;i++) {
if ((pid[i] = fork()) == 0) exit(100 + i);
}
i = 0;
while ((retpid = waitpid(pid[i++], &status, 0)) > 0) {
if (WIFEXITED(status)) {
printf("%d\n", status);
printf("child %d terminated normally with exit status = %d\n",
retpid, WEXITSTATUS(status));
} else printf("child %d terminated abnormally\n", retpid);
}
// if (errno != ECHILD) unix_error("waitpid error");
exit(0);
return 0;
}
wait () 系统调用暂停当前进程的执行,直到其子进程之一终止。调用wait(&status)等价于:
waitpid(-1, &status, 0);
waitpid () 系统调用暂停当前进程的执行,直到由 pid 参数指定的子进程改变状态。默认情况下, waitpid () 仅等待终止的子进程,但此行为可通过 options参数进行修改,如下所述。
标签 | 描述 |
---|---|
< -1 | 意思是等待任何进程组 ID 等于pid绝对值的子进程。 |
-1 | 意思是等待任何子进程。 |
0 | 意思是等待任何进程组ID等于调用进程的子进程。 |
> 0 | 意思是等待进程 ID 等于pid值的子进程。 |