int fork(void);
返回值:函数的奇妙之处在于调用一次,返回两次,可能有3种不同的返回值
成功:父进程中,fork返回新创建的子进程的PID
子进程中,fork返回0
失败:返回-1
int vfork(void);
fork: 子进程拷贝父进程的数据段,代码段
vfork: 子进程与父进程共享数据段和堆栈空间,所以子进程对变量修改和父进程会同步。
fork: 子进程和父进程运行次序不固定,由系统调度决定
vfork: 子进程会先于父进程运行
void exit(int status);
void _exit(int status);
pid_t getpid(void);
pid_t getppid(void);
函数功能:阻塞父进程,直到某个子进程退出
头文件:
#include
#include
函数原型
pid_t wait(int *status);
形参:
*status:获取子进程结束状态值,获取到status后用 WEXITSTATUS(status) 来转换子进程退出时的退出码
对于转换就是返回值%0377(八进制数)等效于于对256取余
返回值
函数功能:阻塞调用进程,直到某个子进程退出
头文件:
#include
#include
函数原型
pid_t waitpid(pid_t pid, int *status, int options);
形参:
pid:欲等待的子进程识别码
参数值 | 说明 |
---|---|
pid<-1 | 等待进程组号为pid绝对值的任何子进程。 |
pid=-1 | 等待任何子进程,此时的waitpid()函数就退化成了普通的wait()函数。 |
pid=0 | 等待进程组号与目前进程相同的任何子进程,也就是说任何和调用waitpid()函数的进程在同一个进程组的进程。 |
pid>0 | 等待进程号为pid的子进程。 |
*status:保存子进程的状态信息,有了这个信息父进程就可以了解子进程为什么会退出,是正常退出还是出了什么错误
宏名 | 说明 |
---|---|
WIFEXITED(status) | 如果子进程正常结束,它就返回真;否则返回假。 |
WEXITSTATUS(status) | 如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的结束代码。 |
WIFSIGNALED(status) | 如果子进程因为一个未捕获的信号而终止,它就返回真;否则返回假。 |
WTERMSIG(status) | 如果WIFSIGNALED(status)为真,则可以用该宏获得导致子进程终止的信号代码。 |
WIFSTOPPED(status) | 如果当前子进程被暂停了,则返回真;否则返回假。 |
WSTOPSIG(status) | 如果WIFSTOPPED(status)为真,则可以使用该宏获得导致子进程暂停的信号代码。 |
options:控制waitpid()函数的行为。如果不想使用这些选项,则可以把这个参数设为0。
参数 | 说明 |
---|---|
WNOHANG | 如果pid指定的子进程没有结束,则waitpid()函数立即返回0,而不是阻塞在这个函数上等待;如果结束了,则返回该子进程的进程号。 |
WUNTRACED | 如果子进程进入暂停状态,则马上返回。 |
返回值
示例:
#include
#include
#include
#include
#include
int main()
{
pid_t pid, childpid;
int status = 0;
pid = fork();
if (pid < 0)
printf("Error occured on forking.\n");
else if (pid == 0) //子进程
{
sleep(3); //换成3s,然后kill -9 子进程pid
exit(0);
}
else //父进程
{
//返回后继续执行父进程的代码段
}
printf("pid:%d\n",pid); //打印子进程id
do
{
childpid = waitpid(pid, &status, WNOHANG);
if (childpid == 0)
{
printf("No child exited,ret = %d\n", childpid);
sleep(1);
}
} while (childpid == 0);
if (WIFEXITED(status))
printf("正常退出:%d\n",childpid);
if(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)
printf("被SIGKILL信号结束\n");
}
正在执行的进程本身的pcb,mm_struct,页表等信息不会发生改变,仅仅把一个新的程序代码和数据替换了原来进程的代码和数据;这就是进程程序的替换;进程程序替换并不会创建新的进程,它只会加载程序的代码和数据,去替换原来的进程
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 pipe(int fd[2]);
//实例
int fd[2] = {0};
int r = pipe(fd);
int mkfifo(const char* pathname,mode_t mode);
int shmget(key_t key,size_t size,int shmflg);
形参:
key:通常是ftok函数返回的PID
key_t ftok(const char *pathname, int proj_id);
//pathname:可访问的路径;proj_id:就是PID可指定任意整型数据也可使用getpid()
size:创建共享内存大小,以字节为单位
shmflg
返回值
void* shmat(int shmid,const void* shmaddr,int shmflg);
int shmdt(const void* shmaddr);
int shmdt(const void* shmaddr);
int shmctl(int shmid,int cmd, struct shmid_ds *buf);
形参
名称 | 说明 |
---|---|
IPC_STAT | 将共享内存的信息复制到buf |
IPC_SET | 将buf中的数据共享到内存信息 |
IPC_RMID | 删除共享内存 |
IPC_LOCK | 不让共享内存置换到SWAP |
IPC_UNLOCK | 允许共享内存置换到SWAP |
IPC_LOCK和IPC_UNLOCK只有root可以使用
返回值
//buf指向的结构体原型
/usr/include/linux/shm.h struct shmid_ds
{
struct ipc_perm shm_perm; /* 操作权限 */
int shm_segsz; /* 共享内存大小 (bytes) */
__kernel_time_t shm_atime; /* 最近映射的时间 */
__kernel_time_t shm_dtime; /* 最近断开的时间 */
__kernel_time_t shm_ctime; /* 最近改变结构数据时间 */
__kernel_ipc_pid_t shm_cpid; /* 创建共享内存的进程ID */
__kernel_ipc_pid_t shm_lpid; /*最新操作共享内存的进程ID */
unsigned short shm_nattch; /*当前映射到该段的进程的个数 */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* 系统预留 */
};
int msgget(key_t key,int msgflg);
形参
key:是一个键值,用于标识消息队列。可以指定也可以通过ftok函数计算获得
//将指定的文件,和整数标识符转换成key_t类型的数据
key_t ftok(const char *pathname, int proj_id);
//pathnam:指定的文件/路径
//proj_id:整数标识符
msgflg:消息队列建立标志和存储权限
返回值:
//消息队列结构体
struct msgbuf
{
long mtype; /* 区分消息队列 */
char mtext[1]; /* 需要发送的数据 */
};
int msgsnd(int msgid,const void* msgp,size_t msgsz,int msgflg);
size_t msgrcv(int msgid, void* msgp,size_t msgsz,long msgtype,int msgflg);
int msgctl(int msgid,int cmd, struct msqid_ds *buf);
形参
msgid:消息队列标识符;msgget函数返回的消息队列标识码
cmd:操作模式
名称 | 说明 |
---|---|
IPC_STAT | 将消息队列信息复制到buf |
IPC_SET | 将buf信息复制到消息队列 |
IPC_RMID | 删除消息队列 |
IPC_INFO | 获取消息队列的limit信息 |
*buf:指向struct_msgid_ds 结构体的指针
//struct_msgid_ds结构体
/ usr / include / linux / msg.h 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; /*最后接收消息的进程号*/
};
返回值
void (*signal(int sig, void (*func)(int)))(int);
int raise(int sig);
int kill(pid_t pid,int sig);
形参
pid:进程描述符(pid)
参数 | 描述 |
---|---|
pid>0 | 将信号发送给进程ID为pid 的进程。 |
pid=0 | 将信号发送给和当前进程相同进程组的所有进程; |
pid=-1 | 将信号广播发送给系统内所有的进程; |
pid<-1 | 将信号发送给进程组号为pid绝对值的所有进程 |
sig:信号ID
返回值
函数功能:阻塞或解除阻塞一个或多个信号
阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。
头文件
函数原型
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
形参
how:操作方式
参数 | 说明 |
---|---|
SIG_BLOCK | 把 set指向的信号集中的信号添加到当前信号屏蔽字中。 |
SIG_UNBLOCK | 从当前信号屏蔽字中移除 set指向的信号集中的信号。 |
SIG_SETMASK | 用 set指向的信号集替换当前信号屏蔽字。 |
*set:指向需要修改的信号集替换当前信号屏蔽
oldset:原有的信号集,可以设置为NULL
返回值
int sigqueue(pid_t pid, int sig, const union sigval value);
形参
pid:目标程序描述符(pid)
sig:需要发送的信号
value:携带的数据
union sigval
{
int sival_int;
void *sival_ptr;
};
返回值
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
signum:需要捕获的信号
*act:信号处理方式
struct sigaction
{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}