一、守护进程程序编写框架 ==》5 步骤
1、创建孤儿进程 ==》fork 父进程退出,子进程保留
fork()
exit() ===>父进程
2、创建会话组组长 ===>独立session
setsid()===> pid_t setsid(void);
功能:将当前进程脱离终端控制变为会话组组长权限。
参数:无
返回值:成功 返回当前会话组组长pid
失败 -1;
/home/linux/123/
3、修改工作目录 ===》不被卸载
chdir("/");
chdir() ===int chdir(const char *path);
功能:修改当前工作进程的工作目录。
参数:path 要修改到的目的工作目录。
返回值:成功 0
失败 -1;
4、修改权限掩码 ===》 提权
umask(0)
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
功能:修改当前环境下的文件权限掩码
参数:mask 要修改的目标掩码,在守护进程
中该值为 0,表示目标权限全部放开。
返回值:成功 修改之后的文件权限掩码
失败 -1;
5、关闭文件描述符===>清理文件 0 1 2
close() ==》getdtablesize() 1024
int getdtablesize(void);
功能:0
参数:无
返回值:成功 最大描述符
失败 -1;
6、验证是否是一个守护进程
6.1 ps aux ==>STAT 列 ===》会话组长 Ss
6.2 ps aux ==>TTY 列 =? ==》表示没有终端关联
6.3 ps -ef ==>ppid =1 ===>孤儿进程
ps -eo pid,ppid,stat,tty,comm
必须满足以上三个要求,则为守护进程.
如果要关闭守护进程则需要使用命令 kill +pid 或 kill -9 +pid
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
pid_t pid;
pid =fork();
if(pid > 1)
{
printf("%d\n", pid);
exit(1);
}
if(0 == pid)
{
setsid();
chdir("/");
umask(0);
int i;
for(i = 0; i < 1024; ++i)
close(i);
while(1)
{
printf("++++++++++++");
sleep(1);
}
}
if(pid < 0)
{
exit(1);
}
return 0;
}
用进程的方式,打开程序来完成minishell
此版本要自己写许多选择有些low
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
char path[256];
char cmd[256] = {0};
while(1)
{
char *arg[4] = {NULL};
while(1)
{
getcwd(path, 256);
printf("linux/@ubuntu %s$", path);
fgets(cmd, 256, stdin);
cmd[strlen(cmd)-1] = '\0';
if( strlen(cmd) !=0)
break;
}
arg[0] = strtok(cmd, " ");
arg[1] = strtok(NULL, " ");
arg[2] = strtok(NULL, " ");
arg[3] = strtok(NULL, " ");
if(0 == strcmp(arg[0], "quit"))
{
break;
}
pid_t pid = fork();
if(pid > 0)
{
printf("%d\n", pid);
wait(NULL); //等待回收子进程
}
if(0 == pid)
{
if(0 == strcmp(arg[0], "ls"))
{
//int execlp(const char *file, const char *arg, ...); execl()函数为最初的。 此处的execlp(); 包含了环境变量。
execlp("ls", "ls", arg[1], arg[2], arg[3], NULL);
exit(1);
}
if(0 == strcmp(arg[0], "cp"))
{
//int execlp(const char *file, const char *arg, ...);
execlp("cp", "cp", arg[1], arg[2], arg[3], NULL);
exit(1);
}
if(0 == strcmp(arg[0], "cat"))
{
//int execlp(const char *file, const char *arg, ...);
execlp("cat", "cat", arg[1], arg[2], arg[3], NULL);
exit(1);
}
}
if(pid < 0)
{
exit(1);
}
}
return 0;
}
此为Plus 版本
将命令写到一个数组中
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
char path[256];
char cmd[256] = {0};
while(1)
{
char *arg[10] = {NULL};
while(1)
{
getcwd(path, 256);
printf("linux/@ubuntu %s$", path);
fgets(cmd, 256, stdin);
cmd[strlen(cmd)-1] = '\0';
if( strlen(cmd) !=0)
break;
}
arg[0] = strtok(cmd, " ");
int i;
for(i = 1; i < 10; ++i )
{
arg[i] = strtok(NULL, " ");
}
if(0 == strcmp(arg[0], "quit"))
{
break;
}
if(0 == strcmp(arg[0],"cd")) //此处可以切换路径
{
chdir(arg[1]);
continue; // 跳出本单次循环可以回到前面重新执行。
}
pid_t pid = fork();
if(pid > 0)
{
printf("%d\n", pid);
wait(NULL); //此处等待子进程回收。
}
if(0 == pid)
{
//int execvp(const char *file, char *const argv[]); 此处execlvp() 包含了环境变量,还包含了数组矢量 vector 。
execvp(arg[0], arg);
exit(1);
}
if(pid < 0)
{
exit(1);
}
}
return 0;
}
创建子线程,在主线程中开辟结构体空间,在子线程中写入内容,然后子线程退出,主线程回收子线程参数。最后在主线程中读出写入结构体中的值。
方法一:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char name[100];
char age[50];
char addr[100];
}Per;
void *th(void * arg)
{
printf("the second thread_id is %lu\n", pthread_self());
Per *p = (Per *)arg;
printf("please input name:\n");
scanf("%s", p->name);
printf("please input age:\n");
scanf("%s", p->age);
printf("please input addr:\n");
scanf("%s", p->addr);
printf("recieve over!\n");
pthread_exit(p);
}
int main(int argc, const char *argv[])
{
Per per;
Per *temp;
temp = &per;
pthread_t tid;
pthread_create(&tid, NULL, th, temp);
void *ret;
printf("the main thread_id is %lu\n", pthread_self());
pthread_join(tid, &ret);
printf("name: %s age: %s addr:%s \n", ((Per *)ret)->name, ((Per *)ret)->age, ((Per *)ret)->addr);
return 0;
}
方法二;
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char name[100];
char age[50];
char addr[100];
}Per;
void *th(void * arg)
{
printf("the second thread_id is %lu\n", pthread_self());
Per *p = (Per *)arg;
printf("please input name:\n");
fgets(p->name, 100, stdin);
printf("please input age:\n");
fgets(p->age, 100, stdin);
printf("please input addr:\n");
fgets(p->addr, 100, stdin);
printf("recieve over!\n");
pthread_exit(p);
}
int main(int argc, const char *argv[])
{
Per *temp;
temp = malloc(sizeof(Per));
pthread_t tid;
pthread_create(&tid, NULL, th, temp);
void *ret;
printf("the main thread_id is %lu\n", pthread_self());
pthread_join(tid, &ret);
Per *p = (Per *)ret;
puts(p->name);
puts(p->age);
puts(p->addr);
free(temp);
return 0;
}
用scanf() 和fgets(); 接收时有些区别。 前者遇见空格及回车都会认为输入结束,因此不能用前者输入带空格的字符。 后者则可以接收空格。