/*
* 这是一个UNIX & LINUX
下开发使用的常量信息整理文档。
* 可以查找常量使用于取值信息。
*
*/ 环境变量
name
=value
#
include <stdio.h
>char *getenv(
const char * name)
返回:指向name的value的指针,若为找到返回NULL
POSIX.
1 和XPG3的基础环境变量
-------------------------------------------------------环境变量 标准 实现 说明
--------------------------------- POSIX.
1 XPG3 SVR4
4.
3+BSD
-------------------------------------------------------HOME
* * * * 起始目录
LANG
* * * 本地名
LC_ALL
* * * 本地名
LC_COLLATE
* * * 本地排序名
LC_CTYPE
* * * 本地字符分类名
LC_MONETARY
* * * 本地货币编辑名
LC_NUMERIC
* * * 本地数字编辑名
LC_TIME
* * * 本地日期
/时间格式名
LOGNAME
* * * * 登录名
NLSPATH
* * 消息类模板序列
PATH
* * * * 搜索可执行文件的路径前缀表
TERM
* * * * 终端类型
TZ
* * * * 时区信息
------------------------------------------------------- 对各种环境表函数的支持
------------------------------------------------------- 函数 标准 实现
--------------------------------------------- ANSI C POSIX.
1 XPG3 SVR4
4.
3+BSD
------------------------------------------------------- getenv
* * * * *putenv 可能
* * * setenv
* unsetenv
* clearenv 可能
------------------------------------------------------- #
include <stdlib.h
>int putenv(
const char *str);
int
setenv(
const char *name,
const char *value,
int
rewrite);
返回:若成功返回
0 ,失败为非
0void unsetenv(
const char *name);
//删除指定的环境变量。setjmp longjmp 函数
不允许使用
goto语句。进行跳转功能,可以通过setjmp和longjmp.
#
include <setjmp.h
> int
setjmp(jmp_buf env);
void longjmp(jmp_buf
env,
int val);
返回:直接调用返回
0 若从logjmp返回非
0自动、寄存器和易失变量
如果longjmp 返回调用函数后不不希望变量值进行回滚着使用
volatile进行定义。
sigsetjmp 和siglongjmp
信号跳转控制。
getrlimit和setrlimit函数
每个进程都有一组资源限制通过getrlimit和setrlimit函数查询和更改。
#
include <sys
/time.h
>#
include <sys
/resource.h
>int getrlimit(
int
resource,
struct relimitr lptr);
int setrlimit(
int
resource,
const struct relimitr lptr);
返回:成功为
0 ,失败为非
0struct rlimit{
rlim_t rlim_cur;
//soft limit : current limit rlim_t rlim_max;
//hard limit : maximum value for rlim_cur
}
资源限制原则
1 任何一个进程都可将一个软限制更改为小于或等于其应限制。
2
任何一个进程都可降低其硬制值,但它必须大于或等于其软件限制值。这种降低,对普通用户而言是不可逆反的。
3 只有超级用户可以提高硬限制。
无限量的限制由常数RLIM_IMFINITY指定。
resource
的取值
RLIMIT_CORE core 文件的最大字节数,若其值为
0则阻止创建core文件。
RLIMIT_CPU CPU时间的最大量值(秒),当超过此软件限制时,向该进程发送SIGXCPU信号。
RLIMIT_DATE 数据段的最大字节长度。
RLIMIT_ESIZE 可以创建的文件最大字节长度。超过此软限制时,则向该进程发送SIGXFSZ信号。
RLIMIT_MEMLOCK
锁定在存储器地址空间(尚未实现)
RLIMIT_NOFILE 每个进程能打开的最多文件数,更改此限制将影响到sysconf函数在参数_SC_OPEN_MAX中的返回值。
RLIMIT_NPORC 每个实际用户ID所拥有的最大子进程数。更改此限制将影响到sysconf函数在参数_SC_CHILD_MAX返回值。
RLIMIT_RSS 最大驻内存集字节长度(RSS).
RLIMIT_STACK 栈的最大字节长度。
RLIMIT_VMEM 可映照地址空间的驻地啊字节长度。影响到mmap函数。
资源限制可以被子进程继承。
第
8 章 进程控制
@进程标识
#
include <sys
/types.h
>#
include <unistd.h
>pid_t getpid(
void);
//返回:调用进程的进程IDpid_t getppid(
void);
//返回:调用进程的父进程ID uid_t getuid(
void);
//返回:调用进程的实际用户IDuid_t geteuid(
void);
//返回:调用进程有效用户IDgid_t getgid(
void);
//返回:调用进程的实际组IDgid_t getegid(
void);
//返回:
调用进程的有效组ID@ fork函数
创建一个继承
#
include <sys
/types.h
>#
include <unistd.h
>pid_t fork(
void);
//返回:子进程中为0
,父进程中子进程ID,出错返回-1. #
include <sys
/types.h
> #
include <sys
/wait.h
>pid_t wait(
int *stalioc);
pid_t
waitpid(pid_t pid,
int *statloc,
int
optinos);
//返回:成功返回ID
错误返回-1 #
include <sys
/wait.h
>int waitid(idtype_t idtype,id_t id,siginfo_t
*infop,
int
options);
/*
idtype:
P_PID 等待一个特定的进程,id要等待的进程ID
P_PGID 等待一个特定的进程组中的任何一个子进程,id包含要等待的子进程的进程组ID
P_ALL 等待任一子进程,忽略id
options:
WCONTINUED 等待一个进程,它以前曾被暂停,此后又被继续,但其状态尚未报告
WEXITED 等待已退出的进程
WNOHANG 如无可用的子进程退出状态,立即返回而非阻塞。
WNOWAIT 不被坏子进程退出状态,该子进程退出状态可由后续的wait,waitid
或waitpid调用取得
WSTOPPED 等待一个进程,他已经暂停,但其状态尚未报告。
*/#
include <unistd.h
>int execl(
const char *pathname,
const char *arg0,...
/* (char *))*/);
int
execv(
const char *pathname,
char *const argv[]);
int execle(
const
char *pathname,
const char
*arg0, ... ,
/* (char *)0 ,char
*const envp[]*/);
int execve(
const char *pathname,
char *const argv[],
char *const envp[]);
int execlp(
const
char *filename,
const char
*arg0, ...);
int
execvp(
const char *filename,
char *const argv[]);
/*
*
pathname 和 filename 为空时从当前路径开始搜索文件,
* 也PATH 环境变量收索BIN文件。
*
* execlp
和 execvp 执行的事/bin/sh 脚本不是BIN文件。filename 为输出文件
* *//* 改变用户ID和组ID*/#
include <unistd.h
>int setuid(uid_t
uid);
int setgid(gid_t gid);
/* BSD支持 交换实际用户ID和有效用户ID的值 */#
include <unistd.h
>int
setreuid(uid_t ruid,uid_t euid);
int
setregid(gid_t rgid,gid_t egid);
/* 只更改有效哟用户ID和有效组ID
*/#
include <unistd.h
>int seteuid(uid_t uid);
int setegid(gid_t gid);
#
include <stdlib.h
>/*
使用是需要注意权限漏洞,避免在同意进程中于设置权限函数一起使用 */int system(
const
char*cmdstring);
/*进程
会记*/#
include <sys
/acct.h
>/* 为列入规范中,有平台差异性
*
当进程结束后会记录关的进行信息,如启动时间,
* 消耗CPU 时间等信息。*//* 结构体
*//*struct acct
;
ac_flag:
FreeBSD 5.2.1 Linux
2.4.22 Mac OS X 10.3 Solarn
9
AFORK 进程是由fork产生的。但从未调用exec Y Y Y Y
ASU 进行使用超级用户特权 N Y Y Y
ACOMPAT
进行使用兼容模式 N N N N
ACORE 进程转储core Y Y Y N
AXSIG 进行由信号杀死 Y Y Y N
AEXPND 扩展的会记条目 N N N Y
*//* 用户标示 */#
include
<unistd.h
>char *getlogin(
void);
/* 成功返回登录信息,失败返回NULL
*//* 进程时间 */#
include <sys
/times.h
>clock_t
times(
struct tms
*buf);
/* 成功返回时间,失败返回 -1
*/struct tms{
clock_t
tms_utime;
/* user CPU time */clock_t tms_stme;
/* system cpu time */clock_t tms_cutime;
/* user CPU time terminated children */clock_t
tms_cstime;
/* system CPU time ,terminated
children*/};
/* 进程组
*/#
include <unistd.h
>/* 返回进行的进程组ID */pid_t getpgrp(
void);
pid_t getpgid(pid_t pid);
/* pid =0 等同于调用 getpid(); 成功返回组ID,失败返回-1*/int setpgid(pid_t pid,pid_t pgid);
/* 成功返回0 失败返回-1
如果 pid = pgid 这pid
的ID将变成这个组的组长
*//* 会话 (session) :
是多个进程组的集合 */#
include <unistd.h
>pid_t
setsid(
void);
/* 成功返回进程组ID
失败返回-1*/pid_r getsid(pid_t pid);
/* 取得会话ID
成功返回首进程的进程组ID,失败返回-1 *//* pid =0 返回进行的会话首进行的进程组ID
有权限限制可能失败 *//* 控制终端 */#
include <unistd.h
>pid_t tcgetpgrp(
int fileds);
/*
成功返回前台进程组ID,失败返回-1 */int
tcsetpgrp(
int filedes, pid_t pgrpid);
/* 成功返回0 , 失败返回-1 */#
include <termios.h
>pid_t
tcgetsid(
int filedes);
/*
成功返回会话首进程的进程组ID 失败返回-1 *//* 作业控制
*//*
1 支持作业控制的shell
2
内核中的终端驱动程序必须支持作业控制
3 内核必须提供对某些作业控制信号的支持
中断字符 Ctrl + C
SIGINT
退出字符 Ctrl + \ SIGQUIT
挂起字符 Ctrl + Z
SIGTSTP
*//* 孤儿进程 *//*
孤儿进程 精灵进程
编程规则
1
首先做的是调用fork,然后使用父进程exit。
第一点如果该精灵进程是由一条简单的shell命令启动的。那么使父进程终止使得shell认为这条命令执行完成。
第二点只进程继承了父进程的进程组ID,但具有一个新的进程ID,这就保证了子进程不是一个进程组的首进程,
2
调用setsid以创建一个新的对话期。
3
将当前工作目录改为根目录。如果精灵进程的当前工作目录在一个装备文件系统中,那么该文件系统就不能被卸载。
4 将文件方式创建屏蔽字设置为0。
若精灵进程要创建一个组可读,写的文件,而集成的文件方式创建屏蔽字,屏蔽了这两种许可权,这所要求的组可读,写就不能起作用。
5
关闭不再需要的文件描述符。这样使精灵进程就不再持有从其父进程继承来的末写文件描述符。
一个进程的父进行以终止,的子进程成为孤儿进程被init
所收养
session 结构
s_count 是该会话中的进程组数,当此计数器减到0时释放该结构
s_leader
是指向会话首进程proc结构的指针
s_ttyvp 是指向控制终端vnode结构指针
s_ttyp 是指向控制终端tty结构指针
s_sid 是会话ID,请记住会话ID这一概念并非Sigle
UNIX Specification
的组成部分
tty 结构
t_session
指向将此终端作为控制终端的session结构
t_pgrp 指向前台进程组的pgrp结构,终端驱动程序用此字段将信号送至前台进程。
t_tremios
是包含所有这些特殊字符以及于该终端有关信息
t_winsize
是包含终端窗口当前尺寸的winsize结构,改变窗口尺寸是发送SIGWINCH信号
pgrp 结构
pg_id
是进程ID
pg_session 指向此进程组成员会话session结构
pg_members 是指向作为此进程组成员的proc结构列表指针。
proc 是双向链表
proc 结构
p_pid 包含进程ID
p_pptr 是指向父进程proc结构的指针
p_pgrp
是指向本进程所有组的pgrp结构指针
信号
-------------------------------------------------------------------------------------------------------
名字
说明 ISO C SUS FreeBSD Linux Mac OS X Solaris
默认动作
-------------------------------------------------------------------------------------------------------
SIGABRT 异常终止(abort) Y Y
Y Y Y Y 终止+
code
SIGALRM 异常终止(alarm) N Y Y Y Y
Y 终止
SIGBUS 硬件故障 N Y Y
Y Y Y 终止+
code
SIGCACEL 线程内部使用 N N N N N
Y 忽略
SIGCHLD 子进程状态改变 N Y Y
Y Y Y 忽略
SIGCONT 使暂停进程继续
N Y Y Y Y Y
继续/忽略
SIGEMT 硬件故障 N N Y Y Y
Y 终止+ code
SIGFPE 算数异常 Y Y
Y Y Y Y 终止+
code
SIGFREEZE 检查点冻结 N N N N N
Y 忽略
SIGHUP 链接断开 N Y Y
Y Y Y
终止
SIGILL 非法硬件指令 Y Y Y Y Y
Y 终止+ code
SIGINFO 键盘状态请求 N N Y
N Y N 忽略
SIGINT 终端中断符
Y Y Y Y Y Y
终止
SIGIO 异步I/O N N Y Y
Y Y 终止/忽略
SIGIOT 硬件故障 N N
Y Y Y Y 终止+ code
SIGKILL 终止
N Y Y Y Y Y
终止
SIGLWP 线程库内部使用 N N N N N
Y 忽略
SIGPIPE 写至无读进程的管道 N Y Y
Y Y Y
终止
SIGPOLL 可轮询事件(poll) N XSI N Y N
Y 终止
SIGPROF 时间超时(settimer ) N XSI Y
Y Y Y
终止
SIGPWR 电源失效/重启 N N N Y N
Y 终止/忽略
SIGQUIT 终端退出符 N Y Y
Y Y Y 终止+
code
SIGSEGV 无效内存引用 Y Y Y Y Y
Y 终止+ code
SIGSTKFLT 协处理器栈故障 N N N
Y N N
终止
SIGSTOP 停止 N Y Y Y Y
Y 暂停进程
SIGSYS 无效系统调用 N XSI Y
Y Y Y 终止+
code
SIGTERM 终止 Y Y Y Y Y
Y 终止
SIGTHAW 检查点解冻 N N N
N N Y
忽略
SIGTRAP 硬件故障 N XSI Y Y Y
Y 终止+ code
SIGTSTP 终端停止符 N Y Y
Y Y Y
暂停进程
SIGTTIN 后台读控制tty N Y Y Y
Y Y 暂停进程
SIGTTOU 后台写至控制tty N Y
Y Y Y Y
暂停进程
SIGURG 紧急情况(套接字) N Y Y Y
Y Y 忽略
SIGUSR1 用户定义的信号 N Y
Y Y Y Y
终止
SIGUSR2 用户定义的信号 N Y Y Y Y
Y 终止
SIGVTALRM 虚拟时间闹钟 N XSI Y Y
Y Y 终止
SIGWAITING 线程库内部使用 N N
N N N Y
忽略
SIGWINCH 终端窗口大小改变 N N Y Y Y
Y 忽略
SIGGXCPU 超过CPU限制 N XSI Y
Y Y Y 终止+
code/忽略
SIGXFSZ 超过文件长度限制 N XSI Y Y
Y Y 终止+ code/忽略
SIGXRES 超过资源控制
N XSI N N N Y
忽略
SIGABRT
调用abort
函数时产生这个信号,进程异常终止。
SIGALRM
在用alarm函数设置的计时器超时时,产生信号,
若由setitimer(2)函数设置的间隔时间超时时,也会产生此信号。
SIGBUS
指示一个实现定义的硬件故障,当出现某些类型的内存故障时,
实现常常产生此信号。
SIGCANCEL
是Solarisx线程库内不使用的信号,不共一般应用。
SIGCHLD
在一个进程终止或停止时,将SIGCHLD信号发送给其父进程,按系统默认。
将忽略此信号,如果父进程希望被告知其子进程的这种状态改变,则应捕获此信号
信号捕获函数中通常要调用一种wait函数以取得子进程ID和其终止状态。
线程
线程标示
*/#
include <pthread.h
>int pthread_equal(pthread_t tid1,pthread_t tid2);
// 返回值 : 相等返回非0值,否则返回0//
POSIX 线程的特征测试是_POSIX_THREADS
应用程序可以把这个宏定于#ifdef测试,以在编译时确定是否支持线程。//
也可以把_SC_THREADS常数用于调用sysconf函数,从而在运行时确定是否支持线程。#
include <pthread.h
>ptherad_t
ptherad_self(
void);
// 返回值
: 返回调用线程的ID。/* 线程创建 */#
include <pthread.h
>int pthread_create(pthread_t
*restrict tidp,coust pthread_attr_t
*restrict attr,
void *(
*start_rtn)(
void),
void *restrict arg );
// 返回值 :
当成功返回时,由tidp指向的内存单元被设置为新创建的进程的线程ID。attr参数用于定制各种不同的线程属性。// 可以设置为NULL 创建默认属性的线程。//
新创建的线程在start_rtn函数地址开始执行,该函数只有一个无类型的指针参数arg,如果需要向start_rtn函数传递的阐述不止一个,那么需要参数// 放到结构体中。通过arg 传递给线程处理。//
pthread函数调用失败时不会返回errno 代码。/*线程终止
1
线程只有从启动历程三种方式退出,返回值是线程的腿出码。
2 线程可以被同一进程中的其他线程取消。
3
线程调用pthread_exit. */#
include
<pthread.h
>void pthread_exit(
void *rval_ptr);
//rval_ptr
是一个无类型指针,与传给启动历程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。#
include <pthread.h
>int pthread_join(pthread_t thread,
void **rval_ptr);
//返回值:若成功则返回0,否则返回错误编号。调用线程将一直阻塞,直到指定的线程调用pthread_exit,从启动历程中返回或者被取消。// 调用 pthread_cancle 函数来请求取消同一进程中的其他进程。#
include <pthread.h
>int pthread_cancle(pthread_t tid);
// 返回值:若成功则返回0,否则返回错误号//
默认情况下,pthread_cancle 函数会使得由tid标示的线程的行为表现为如同调用了参数为PTHREAD_CANCELED 的 pthread_exit
函数,但是// 线程可以选择忽略取消方式或是控制取消方式。/* 进程栈操作 */ #
include <pthread.h
>void pthread_cleanup_push(
void (
*rtn)(
void *),
void *arg);ei
void pthread_cleanup_pop(
int execute);
/*
当线程执行一下动作时调用清理函数调用参数为arg,清理函数rtn的调用顺序是由,pthread_cleanup_push函数来安排的
。
1 调用pthread_exit 时
2 响应取消请求。
3 用非零execute
参数调用pthread_cleanup_pop时。
如果 execute =0 清理函数将不被调用。无论那种情况
pthread_cleanup_pop都将删除上次pthread_cleanup_push调用建立的清理处理程序。
注意:
函数有限制,由于他们可以实现为宏。所以必须在与线程相同的作用域中以匹配对应的形式。
进程原于线程原语比较
-------------------------------------------
进程 线程 描述
-------------------------------------------
fork
pthread_create 创建新的控制流
exit
pthread_exit 从现在的控制流中退出
waitpid pthread_join 从控制流中得到退出状态
atexit pthread_cancle_push
注册在退出控制流时调用的函数
getpid pthread_self 获取控制流ID
abort pthread_cancle 请求可控制流的非正常退出
线程进入分离状态
分离状态:进程的终止状态会保存到该线程调用的pthread_join,如果线程已经处于分离状态,线程的地称存粗资源可以在线程终止时立即被回收。
*/#
include <pthread.h
>int pthread_detach(pthread_t tid);
//返回值: 成功返回0,错误返回错误号/*
线程同步
1互斥量
可以通过使用pthread的互斥接口保护数据,确保同一时间只有一个线程访问数据。
需要声明互斥量
pthread_mutex_t
数据类型进行初始化。
PTHREAD_MUTEX_INITIALIZER 进行初始化。
pthread_mutex_t abc =
PTHREAD_MUTEX_INITIALIZER;
*/#
include <pthread.h
>int pthread_mutex_init(pthread_mutex_t
*restrict mutex,
const
pthread_mutexattr
-t
*restrict attr);
int
pthread_mutex_destroy(pthread_mutex_t
*mutex);
//成功返回0
失败返回错误编号。/*
采用默认属性初始化互斥变量,只要把attr设置为NULL。
互斥变量加锁
*/#
include <pthread.h
>int pthread_mutex_lock(pthread_mutex_t
*mutex);
int
pthread_mutex_trylock(pthread_mutex_t
*mutex);
int
pthread_mutex_unlock(pthread_mutex_t
*mutex);
//成功返回0
失败返回错误代码。/*
如果不希望新城被阻塞,可以调用pthread_mutex_trylock尝试加锁
,如果以被加上锁这返回EBUSY。否则返回0.
2避免死锁
读写锁
条件锁
*/ /*
高级进程间通信 IPC
通信方式有 管道 FIFO 消息队列 信号量 共享存储
等几种方式。
1 管道
管道一个双工(全双工)管道。管道是一种流设备,故可以将处理模块压入管道的人一一端。
SVR4
下的s_pipe 函数
*/#
include
<unistd.h
>int pipe(
int
filedes[
2]);
//返回:成功0
出错为0/*
@ popen 和pclose
函数
创建一个链接到另一个进程的管道
*/#
include <stdio.h
>FILE
*popen(
const char *cmdstring,
const char *type);
//返回:成功返回文件指针,错误为NULL /*
cmdstring 为shell 命令
type 取值为 r w
*/int pclose(FILE
*fp);
//返回:cmdstring
的终止状态,若出错则为-1 /*
@ FIFO
命名管道
*/#
include <sys
/types.h
>#
include <sys
/stat.h
>int mkfifo(
const char
parthname,mode_tmode );
// 返回: 若成功返回0
失败返回-1/*
一旦用mkfifo 创建了一个FIFO 就可以open它,( close
,read , write , unlink 等)都可用于FIFO。
O_NONBLOCK 非阻塞标记
FIFO 用途:
1
FIFO由shell使用以便将数据从一条管道线传入另一条,为无需创建中间临时文件。
mkfifo fifo1
prog3 < fifo1
&
prog1 < infile | tee fifo1 |
prog2
创建FIFO,然后在后台启动prog3,它从FIFO读数据。然后启动p读prog1,用tee其输出发送到FIFO和prog2。
2
FIFO客户机-服务器应用程序中,以在客户机和服务器之间传递数据。
消息队列
从消息队列中取消息。
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/msg.h
>int msgget(key_t key,
int flag);
//返回:若成功返回消息ID,错误返回-1。/*
msgctl函数对队列执行多种操作。
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/msg.h
>int msgctl(
int
msqid,
int cmd,
struct msqid_ds buf);
//返回:成功返回0错误返回-1/*
cmd
参数指定对于由msqid的队列要执行的命令:
1 IPC_STAT 取此队列的msqid_ds 结构,并将其存放在buf指向的结构中。
2
IPC_SET 按由buf的结构中的值,设定与此队列相关的结构中的下列4个字段:
msg_perm.uid
msg_perm.gid
msg_perm
mode
msg_qbytes
此命令只能由下列两种进程执行:
一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;
另一种是具有超级用户特权的进程。只有超级用户才能加msg_qbytes的值
3
IPC_RMID
从系统中删除该消息队列以及仍在该队列上的所有数据。为立即生效。
重复删除一条消息时返回EIDRM。
此命令只能有下列两种进程执行:
一种是其有效用户ID等于msg_perm.cuid
或msg_perm.uid
另一种是具有超级用户特权的进程。
IPC_STAT ,IPC_SET
,IPC_RMID 也可以用户共享内存。
将消息插入到消息队列中
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/msg.h
>int msgsnd(
int
msqid,
const void ptr,size_t nbytes,
int flag);
//返回:成功返回0
,错误返回-1/*
从消息队列中取出消息
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/msg.h
>int msgrcv(
int
msqid,
void ptr,size_t nbytes,
long type,
int
flag);
//返回:成功返回消息数据长度,错误返回-1/*
ptr 参数指向一个长整型数,nbytes说明数据缓存长度。若返回的消息大于nbytes,而且在flag中设置了MSG_NOERROR,则
该消息被截断。
type
参数
=0 返回队列中的第一条消息
>0 返回队列中的消息类型为type的第一个消息。
<0
返回队列中消息类型值小于或等于type绝对值。而且在这种消息中,其类型值又最小的消息。
非0 type
用于以非先进献出次序读消息。
信号量
信号量是一个计数器。用于进程对共享数据对像的存储。流程如下:
1
测试控制该资源的信号量。
2 若此信号量为正值,则进程可以使用该资源。进程将信号值减1,表示它使用了一个资源单位。
3 若此进程信号量的值为0
,则进程进入睡眠状态,知道信号量值大于0。若进程被唤醒后,返回第一步。
影响信号量的系统限制
-------------------------------------------
名称 说明
典型值
-------------------------------------------
SEMVMX
任一信号量的最大值 32767
SEMAEM 任一信号量的最大终止时调整值 16384
SEMMNI
系统中信号量集的最大数 10
SEMMNS 系统中信号量集的最大数 60
SEMMSL
每个信号量集中的最大信号量数 25
SEMMNU 系统中undo结构的最大数 30
SEMUME
每个undo结构中的最大undo项数 10
SEMOPM 每个semop调用所包含的最大操作数
10
*//*
获取一个信号量ID.
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/sem.h
>int semget(key_t key,
int nsems,
int
flag);
//返回:成功返回信号量ID,出错返回-1/*
信号量的多种操作
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/sem.h
>int semctl(
int
semid,
int semnum,
int cmd,
union
semurarg);
/*semurarg 是联合,而非指向联合的指针
union
semun{
int val; //for SETVAL
struct semid_ds *buf;//for IPC_STAT
and IPC_SET
ushort *array; // for GETALL and SETALL
}
cmd
有10中命令
IPC_STAT 对此集合取semid_ds结构,并存放在由arg.buf指向的结构中。
IPC_SET 按由arg.buf
指向的结构中的值设置与此集合相关结构中的下列3个字段值:
sem_perm.uid,sem_perm.gid和sem_perm.mode
。此命令只能由下列两种进程执行:一种是其有效用户ID等于sem_perm.cuid或sem_perm.uid
的进程,另一种是具有超级用户特权的进程。
IPC_RMID
从系统中删除该信号量集合。
GETVAL 返回成员semnum的semval值。
SETVAL
设置成员semnum的semval值。该值由arg.val指定。
GETPID 返回成员semnum的sempid值。
GETNCNT
返回成员semnum的semncnt值。
GETZCNT 返回成员semnum的semzcnt值。
GETALL
取该集合中的所有信号量的值,并将它们存放在由arg.array的数组中。
SETALL
按arg.array指向的数据组中的值设置该集合中所有信号量的值。
自动执行信号量集合上的操作数组。
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/sem.h
>int semp(
int
semid,
struct sembuf semoprarray[],size_t
nops);
/*返回:成功为0,失败为-1
semoprarray
是个指针指向信号量的操作数组。
struct sembuf{
ushort sem_num;//member # in set
(0,...1,,nsems-1 )
short sem_op; //operation (negative,0 ,or
pasitive)
short sem_flg;//IPC_NOWAIT,SEM_UNDO
}
sem_op
:可以取负值、0或正值。
1 取正值,返回进程占用的资源。
2
取负值,表示要获取由该信号量控制的资源。若信号量的值大于或等于sem_op绝对值,则从信号量值中减去
sem_op的绝对值。这保证信号量的结果值大于活等于0。如果指定了undo标志,这sem_op的绝对值也加到该进程的此信号量调整值上。
如果信号量值小于sem_op绝对值
a 若指定了IPC_NOWAIT ,则出错返回EAGAIN;
b 若未指定IPC_NOWAIT ,这该信号量的semncnt值加1
进入睡眠状态,然后调用进程被挂起直至下列事件之一发生:
i 此信号量变成大于或等于sem_op的绝对值
(某个进程已是放了某些资源),此信号量的semncnt值减1 (进程结束等待),
并信号量值中减去sem_op的绝对值。如果指定了undo标示,则sem_op绝对值也加到该进程的此信号量调整值上。
ii
从系统中删除此信号量。在此情况下函数出错返回ERMID.
iii 进程捕捉到一个信号,并从信号处理程序返回。信号量的semncnt
值减1 不在等待 并返回错误EINTR.
3 若sem_op为0, 这表示希望等待到该信号量编程0,如果信号量值当前是0
,此时函数立即返回。
如果非0 则:
a 若指定了IPC_NOWAIT,则出错返回EAGAIN;
b 若末个指定IPC_NOWAIT
,则该信号量的semncnt值加1 将进入
睡眠状态,然后调用进程被挂起,直至下一列事件之一发生:
i 此信好量值变成0.此信号量的semzcnt值减1
(已经结束等待)。
ii 从系统中删除了此信号量。在此情况下,函数出错返回ERMID。
iii
进程捕捉到一个信号,并从信号处理程序返回。在此情况下 ,此信号量的semzcnt 值减1 (因不在等待),并且函数返回EINTR.
nops
规定该数据中操作的数量(元素数)。
共享内存
共享内存结构体
struct
shmid_ds{
struct ipc_perm shm_perm;// see section 14.6.2
struct
anon_map *shm_amp;// pointer in keernel
int shm_segsz; //size of
segment in bytes
ushort shm_lkcnt; //number of times segment is being
locked
pid_t shm_lpid; //pid of last shmop()
pid_t shm_cpid; //pid of creator
ulong shm_nattch;//number of current
attaches
ulong shm_cnattch;//used onlg for shminfo
time_t
shm_atime; //last-attach time
time_t shm_dtime; //last-detach
time
time_t shm_ctime; //last-change time
}
获得一个共享存储标识符。
*/#
include
<sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/shm.h
>int shmget(key_t
key,
int size,
int flag);
/*
返回:成功返回共享内存ID,失败返回-1
影响共享存储的系统限制
-------------------------------------------
名称 说明 典型值
-------------------------------------------
SHMMAX 共享存储段的最大字节数 131072
SHMMIN 共享存储段的最小字节数 1
SHMMNI 系统中共享存储段的最大段数 100
SHMSEG 每个进程,共享存储段的最大段数 6
共享存储段执行多种操作
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/shm.h
>int shmctl(
int
shmid,
int cmd,
struct shmid_ds
*buf)
/*返回:若成功为0 错误为-1
cmd 5
种,在shmid 指定的端上执行。
IPC_STAT 对此段取shmid_ds结构并存放在buf指的结构中。
IPC_SET 按buf
指向结构中的值设置此段相关结构如下
shm_perm.uid shm_perm.gid shm_perm.mode
此命令只能有下两种进程执行、:一种是shm_perm.cuid
shm_perm.uid, 另一种是超级用户权限。
IPC_RMID
删除系统共享存储段
SHM_LOCK 锁住共享存储段。超级用户执行。
SHM_UNLOCK
解锁共享存储段。超级用户执行。
得到共享存储地址空间
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/shm.h
>void *shmat(
int shmid,
void
*addr,
int
flag);
/*
返回:成功返回指向共享存储段指针,出错返回-1
addr
参数在flag是否能指定SHM_RND 为有关。
addr 取值:
1 如果addr =0 ,则此段连接到由内核选择的第一个可选地址上。
2
如果addr !=0 ,并没有设定SHM_RND,则此段链接到addr知道地址上。
3 如果addr !=0
,并指定了SHM_RND,则此段链接到(addr - (addr mod SHMLBA)) 上所指的地址上。
SHM_RND 意思是:取整 ,SHMLBA
意识是:低边界地址倍数它总是2
的乘方。
结束操作共享存储,调用shmdt脱接该段。并不是从系统中删除其标识符以及其数据结构。
直到某个进程调用shmctl(待IPC_RMID)
特地删除它。
*/#
include <sys
/types.h
>#
include <sys
/ipc.h
>#
include <sys
/shm.h
>int shmdt(
void *addr)
/*
返回:成功返回0 出错返回-1
多个进程映射共享存储空间 4.3+BSD特征
caddr_t
area;
if(( area = mmap(0,SIZE ,PROT_READ | PROT_WRITE,MAP_ANON | MAP_SHARED,
-1,0)) == (cadder_t) -1)
*/
阅读(394) | 评论(0) | 转发(0) |