-----------------------------------------------------守护进程的创建-------------------------------------------------------
------------------------------守护进程(后台进程)的创建------------------------------------
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<syslog.h>
#include<sys/types.h>
#include<unistd.h>
void demon_init(void);
int main(int argc, char const *argv[])
{
demon_init();
//打开日志
openlog("qxjpmm",LOG_PID,LOG_DAEMON);
int fd = open("xx.txt",O_RDWR|O_TRUNC);
if (fd < 0){
syslog(LOG_ERR,"open error");
exit(-1);
}
char buf[20] = "qxj5683pmm";
while(1){
sleep(1);
write(fd,buf,strlen(buf));
syslog(LOG_INFO,"%s",buf);
}
closelog();
close(fd);
return 0;
}
void demon_init(void){
//创建子进程2,结束父进程1
if (fork() != 0){
exit(0);
}
//创建会话
if (setsid() < 0){
perror("setsid error");
exit(-1);
}
//创建子进程3,结束父进程2
if (fork() != 0){
exit(0);
}
//关闭所有的文件描述符
for (int i = 0; i <= sysconf(_SC_OPEN_MAX); i++){
close(i);
}
//改变执行目录----->将执行目录换到根目录
chdir("/");
//修改掩码---->将掩码修改为0 系统默认0002;
umask(0);
//将标准输入,标准输出,标准错误输出全部重定向到null
int fd = open("/dev/null",O_RDWR);
dup(0);
dup(0);
}
----------------------------------------------------进程间的通信方式-----------------------------------------------------
-1>无名管道
主要用途子父进程间的通信
无名管道的API--------->int pipe(int pipefd[2])
头文件: #include <unistd.h>
int pipe(int pipefd[2]);
功能:
创建无名管道
参数:
pipefd[2]:数组 保存 读写 文件描述符
[0]--->读
[1]--->写
返回值:
成功返回0;
失败返回-1,并返回错误码
例如:
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0){
......
}
pid_t pid = fork();
if(pid == 0){
关闭写功能
close(pipefd[1])
char buf[128];
while(1){
读
}
}
if(pid > 0){
关闭读功能
close(pipefd[0])
char buf[128];
while(1){
写
}
}
-2>有名管道
适用于任何进程间的通信
有名管道的API------> int mkfifo(const char *pathname, mode_t mode)
头文件:#include <sys/types.h>
#include <sys/stat.h>
功能:
创建有名管道
参数:
pathname:管道文件的名字(带路径)
mode:权限:0666
返回值:成功返回0;
失败返回-1,并返回错误码
判断某文件是否拥有某功能的API----> int access(const char *pathname, int mode);
头文件:#include <unistd.h>
功能:
判断某文件是否拥有某功能
参数:
pathname:管道文件的名字(带路径
mode:
F_OK:---》文件存在
R_OK:---》文件可读
W_OK:---》文件可写
X_OK:---》文件可执行
返回值:成功返回0;
失败返回-1,并返回错误码
-3>信号
信号是软件层面上对中断机制的一种模拟,是一种异步的通信
信号可以直接进行用户空间进程和内核进程之间的交互。
信号的注册API------> sighandler_t signal(int signum, sighandler_t handler);
头文件: #include <sys/types.h>
#include <signal.h>
typedef void (*sighandler_t)(int);
功能:
信号的注册
参数:
signum:信号
handler:事件
SIG_IGN:忽略
SIG_DFL:默认
捕捉:执行某一个 自定义 的事件 void(*)(int)
返回值:
成功返回sighandler_t
失败返回SIG_ERR并返回错误码
信号的发送API-----------> int kill(pid_t pid, int sig);
功能:
发送信号
参数:
pid:进程的pid号(给谁发)
sig:信号
返回值:
成功返回0
失败返回-1,并返回错误码
-4>共享内存
是进程间的通信最快的一种
共享内存的相关API
1>创建或者获取共享内存API--->int shmget(key_t key, size_t size, int shmflg);
头文件:#include <sys/ipc.h>
#include <sys/shm.h>
功能:创建或者获取共享内存
参数:key:密钥
获取key:
1>IPC_PRIVATE 0 系统自动分配
--->不断生成新的共享内存
2>手动
ftok()的头文件:#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:创建key
参数:
pathname:文件名字(带路径)
proj_id:数字
返回值:
成功返回key
失败返回-1,并返回错误码
注意!!!:
只要pathname和proj_id不变,就可以获得相同的key
例子:
进程A:key_t key1=ftok("xx.txt",5);
进程B:key_t key2=ftok("xx.txt",5);
那么进程A和进程B都可以获得到相同的key
size:共享内存的大小
shmflg:IPC_CREAT|0666
返回值:
成功返回shmid
失败返回-1,并返回错误码
2>将共享内存映射到用户空间API---->void *shmat(int shmid, const void *shmaddr, int shmflg);
头文件:#include <sys/types.h>
#include <sys/shm.h>
功能:
将共享内存映射到用户空间
参数:
shmid:共享内存ID
shmaddr:你想映射的地方(地址)
shmflg:0 可读可写
返回值:
成功返回地址
失败返回-1,并返回错误码
3>解除映射API---->int shmdt(const void *shmaddr);
头文件: #include <sys/types.h>
#include <sys/shm.h>
功能:
解除映射
参数:
shmaddr:映射地址
返回值:
成功返回0
失败返回-1,并返回错误码
4>删除共享内存API----> int shmctl(int shmid, int cmd, struct shmid_ds *buf);
头文件: #include <sys/ipc.h>
#include <sys/shm.h>
功能:
对共享内存进行控制
参数:
shmid:共享内存ID
cmd:IPC_RMID :移除共享内存
buf:IPC_RMID:NULL
返回值:
IPC_RMID
成功返回0
失败返回-1,并返回错误码
-5>信号量/信号灯(临界资源)
在系统V 的信号灯是一个或多个信号灯的集合。其中每一个都是单独的计数信号灯
3>信号灯的相关API(接口)
1>创建或获取信号量API---->int semget(key_t key,int nsems,int semflg)
头文件: #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
功能:
创建或获取信号量
参数:
key:密钥
nsems:信号灯/信号量的个数
semflg:IPC_CREAT|0666
返回值:成功返回semid
失败返回-1,并返回错误码
2>对信号灯进行PV操作API(P为减法,V为加法)----->int semop(int semid,struct sembuf *sops,size_t nsops)
头文件:#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
功能:
对信号灯进行操作
参数:
semid:semget返回的semid值
sops:结构体指针(数组)
struct sembuf{
nsigned short sem_num; /* semaphore number */ 信号灯的下标
short sem_op; /* semaphore operation */操作:+1 +2 -1 -2... PV操作
short sem_flg; /* operation flags */0 可阻塞 IPC_NOWAIT不阻塞
}
nsops:数组中元素的个数
返回值:
成功返回0
失败返回-1
3>删除(控制)信号量API----->int semctl(int semid,int semnum,int cmd, ...)
头文件: #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
功能:
删除(控制)信号量
参数:
semid:semget返回的semid值
semnum:信号量的下标
cmd:
IPC_RMID:删除信号量
GETVAL:获取到信号灯的value值
SETVAL:设置信号灯的value值
GETALL:获取多个信号灯的value值
SETALL:设置多个信号灯的value值
如果cmd不是IPC_RMID,则有第四个参数:这个参数是联合体
union semun {
int val; /* Value for SETVAL */ 设置某个信号灯的值
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */ 设置或获取多个信号灯的值
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
返回值:
GETVAL:成功返回value值
其他成功返回0
失败返回-1,并返回错误码
-6>socket套接字(后续在网络编程更新)