env | grep 2016查路径
写代码完成目录拷贝(注:包含子目录)
#include <stdio.h>
#include <string.h>
#include <errno.h> //errno
/*open stat*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> //read() write()
/*dir ope*/
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h> //exit()
#define PER_IO_BYTES 4096
int fileType(mode_t mode)
{
int ret = -1;
switch (mode & S_IFMT)
{
case S_IFREG:
ret = 0;
break;
case S_IFDIR:
ret = 1;
break;
default:
ret = -1;
break;
}
return ret;
}
void copyRegFile(const char *pDestPathname
, const char *pSrcPathname)
{
//对形参进行有效性检查
if (NULL == pDestPathname || NULL == pSrcPathname)
{
return;
}
int iDestFd = -1;
//以写的方式打开目标文件,如果不存在则创建
iDestFd = open(pDestPathname, O_WRONLY | O_CREAT
, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == iDestFd)
{
perror("open dest");
exit(EXIT_FAILURE);
}
int iSrcFd = -1;
//以读的方式打开源文件,如果不存在则创建
iSrcFd = open(pSrcPathname, O_RDONLY | O_CREAT
, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == iSrcFd)
{
perror("open src");
exit(EXIT_FAILURE);
}
unsigned char caBuf[PER_IO_BYTES] = {'\0'};
int ret = -1;
//从源文件循环读取数据
while ((ret = read(iSrcFd, caBuf, PER_IO_BYTES)))
{
//判断数据读取成功失败与否
if (-1 == ret)
{
//如果发生的错误是EAGAIN,EINTR
//需要重新读取数据
if (EAGAIN == errno || EINTR == errno)
{
continue;
}
//如果是其他错误,则显示错误信息并且退出程序
perror("read src");
//close(iSrcFd);
//close(iDestFd);
exit(EXIT_FAILURE);
}
//如果返回值为0,表示已读到文件末尾,没有数据可读
//则文件拷贝结束
else if (0 == ret)
{
break;
}
while (1)
{
//将读取到的数据写入到目标文件
ret = write(iDestFd, caBuf, ret);
if (-1 == ret)
{
if (EAGAIN == errno || EINTR == errno)
{
continue;
}
perror("write dest");
//close(iSrcFd);
//close(iDestFd);
exit(EXIT_FAILURE);
}
break;
}
}
close(iSrcFd);
close(iDestFd);
}
void copyDirFile(const char *pDestDirName
, const char *pSrcDirName)
{
if (NULL == pDestDirName || NULL == pSrcDirName)
{
return;
}
int ret = -1;
//创建目录
ret = mkdir(pDestDirName, 0775);
if (-1 == ret)
{
if (EEXIST != errno)
{
perror("mkdir");
exit(EXIT_FAILURE);
}
}
DIR *pDestDir = NULL;
//打开目标目录
pDestDir = opendir(pDestDirName);
if (NULL == pDestDir)
{
perror("open dest dir");
exit(EXIT_FAILURE);
}
DIR *pSrcDir = NULL;
//打开源目录
pSrcDir = opendir(pSrcDirName);
if (NULL == pSrcDir)
{
perror("open src dir");
exit(EXIT_FAILURE);
}
char caDestFileName[64] = {'\0'};
char caSrcFileName[64] = {'\0'};
struct stat fileStat;
struct dirent *pDirent = NULL;
pDirent = readdir(pSrcDir);
int iLen = 0;
while (NULL != pDirent)
{
if (0 != strcmp(pDirent->d_name, "..")
&& 0 != strcmp(pDirent->d_name, "."))
{
//拼接路径名
strcpy(caSrcFileName, pSrcDirName);
iLen = strlen(pSrcDirName);
if (pSrcDirName[iLen-1] != '/')
{
strcat(caSrcFileName, "/");
}
strcat(caSrcFileName, pDirent->d_name);
printf("%s\n", caSrcFileName);
/********************************************************/
strcpy(caDestFileName, pDestDirName);
iLen = strlen(pDestDirName);
if (pDestDirName[iLen-1] != '/')
{
strcat(caDestFileName, "/");
}
strcat(caDestFileName, pDirent->d_name);
/********************************************************/
//获得文件status
ret = stat(caSrcFileName, &fileStat);
if (-1 == ret)
{
perror("stat");
exit(EXIT_FAILURE);
}
//判断文件的类型
ret = fileType(fileStat.st_mode);
switch (ret)
{
case 0:
copyRegFile(caDestFileName, caSrcFileName);
break;
case 1:
copyDirFile(caDestFileName, caSrcFileName);
break;
default:
break;
}
}
/********************************************************/
pDirent = readdir(pSrcDir);
}
}
int main(int argc, char *argv[])
{
//copyRegFile(argv[2], argv[1]);
copyDirFile(argv[2], argv[1]);
return 0;
}
鸠占鹊巢(execl,ececlp,execv,execvp)
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
int ret = -1;
//使用新进程镜像替换当前进程镜像
//但是当前进程的ID被新进程使用
//-->鸠占鹊巢,巢还在,鹊变成了鸠
//第一个参数:可执行文件的路径
//之后的参数:可执行文件执行的方式
//ret = execl("/bin/ls", "ls", "/usr/include", "-l", NULL);
//ret = execl("./test", "test", NULL);
//ret = execl("/usr/bin/gedit", "gedit", NULL);
//ret = execl("/usr/bin/gedit", "gedit", "dirCopy.c", NULL);
//可以不指定需要执行文件的路径
//启动该执行文件时,到系统默认路径下去找该执行文件
//若找到了则执行,否则出错返回
//ret = execlp("gedit", "gedit", "dirCopy.c", NULL);
#if 0
ret = execlp("myTest", "myTest", NULL);
printf("ret = %d\n", ret);
if (-1 == ret)
{
perror("execlp");
return -1;
}
#endif
//char *const argv[] = {"ls", "/usr/include", "-l", NULL};
//ret = execv("/bin/ls", argv);
char *const argv[] = {"gedit", "dirCopy.c", NULL};
ret = execvp("gedit", argv);
return 0;
}
eg:execv
#include <stdio.h>
#include <string.h>
/*fork exec*/
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid = -1;
pid = fork();
if (pid > 0) //parent
{
while (1)
{
printf("this is parent\n");
sleep(1);
}
}
else if (0 == pid)
{
//./fe /bin/ls /usr/include -l
int ret = -1;
ret = execv(argv[1], argv+1);
if (-1 == ret)
{
perror("execv");
return -1;
}
}
return 0;
}
运行结果:
管道pipe
#include <unistd.h> //pipe() fork()
#include <stdio.h>
#include <string.h>
//通过pipe()函数创建的管道属于无名管道
//只能在父子进程间或者子进程间使用
//创建该管道的进程一旦结束,则该无名管道将会被销毁
int main(void)
{
int pipefd[2] = {-1};
int ret = -1;
//创建管道,管道两端描述符存储到pipefd数组中
//pipefd[0]表示数据流出端,可以从此端读取数据
//pipefd[1]表示数据进入端,可以往此端写入数据
ret = pipe(pipefd);
if (-1 == ret)
{
perror("pipe");
return -1;
}
pid_t pid = -1;
//管道的创建的创建是在内核中,不独立属于进程
//所以,fork产生子进程是并不会再次创建一个管道
//只是对管道文件描述符进行了一次拷贝
pid = fork();
if (pid > 0) //parent
{
close(pipefd[0]);
while (1)
{
write(pipefd[1], "Hello child", 11);
sleep(1);
}
}
else if (0 == pid) //child
{
close(pipefd[1]);
char caBuf[32] = {'\0'};
while (1)
{
memset(caBuf, '\0', sizeof(caBuf));
read(pipefd[0], caBuf, 11);
printf("%s\n", caBuf);
sleep(1);
}
}
else if (-1 == pid) //fork failed
{
perror("fork");
return -1;
}
return 0;
}
eg:pipe-talk
#include <unistd.h> //pipe() fork()
#include <stdio.h>
#include <string.h>
int main(void)
{
int pipefd[2] = {-1};
int ret = -1;
ret = pipe(pipefd);
if (-1 == ret)
{
perror("pipe");
return -1;
}
pid_t pid = -1;
pid = fork();
if (pid > 0) //parent
{
int iSign = 0;
char caBuf[64] = {'\0'};
while (1)
{
memset(caBuf, '\0', sizeof(caBuf));
if (0 == iSign)
{
printf("parent-input data:");
scanf("%s", caBuf);
write(pipefd[1], caBuf, strlen(caBuf));
iSign = 1;
}
else if (1 == iSign)
{
read(pipefd[0], caBuf, sizeof(caBuf));
printf("child says:%s\n", caBuf);
iSign = 0;
}
sleep(1);
}
}
else if (0 == pid) //child
{
int iSign = 0;
char caBuf[64] = {'\0'};
while (1)
{
memset(caBuf, '\0', sizeof(caBuf));
if (0 == iSign)
{
read(pipefd[0], caBuf, sizeof(caBuf));
printf("parent says:%s\n", caBuf);
iSign = 1;
}
else if (1 == iSign)
{
printf("child-input data:");
scanf("%s", caBuf);
write(pipefd[1], caBuf, strlen(caBuf));
iSign = 0;
}
sleep(1);
}
}
else if (-1 == pid) //fork failed
{
perror("fork");
return -1;
}
return 0;
}
运行结果:
模仿终端
#include <stdio.h>
#include <string.h>
/*fork exec*/
#include <unistd.h>
#include <stdlib.h> //malloc
char *getInput(char *argv[])
{
int ret = -1;
int i = 0;
char *pData = NULL;
pData = (char *)malloc(64);
while (EOF != scanf("%s", pData))
{
printf("%s\n", pData);
argv[i] = pData;
i++;
pData = (char *)malloc(64);
}
free(pData);
argv[i] = NULL;
return NULL;
}
void showArgv(char *argv[])
{
int i = 0;
while (NULL != argv[i])
{
printf("%s\n", argv[i]);
i++;
}
}
int main(void)
{
char *argv[32] = {NULL};
while (1)
{
printf("MyTermal@sq$");
getInput(argv);
pid_t pid = -1;
pid = fork();
if (0 == pid)
{
int ret = -1;
ret = execvp(argv[0], argv);
if (-1 == ret)
{
perror("execv");
return -1;
}
}
}
return 0;
}
运行结果:
atexit
#include <stdio.h>
#include <stdlib.h> //atexit()
#include <unistd.h> //_exit()
void fun1()
{
printf("fun1...\n");
}
void fun2()
{
printf("fun2...\n");
}
void fun3()
{
printf("fun3...\n");
}
//进程正常结束时首先在用户态做一些善后工作
//然后进入内核层做一些善后工作
//return 0 exit() 会首先在用户态做一些善后工作,
// 然后进入内核层做一些善后工作
//_exit() 直接进入内核层做一些善后工作
int main(void)
{
//atexit注册的函数会在进程正常结束后被执行
//执行的顺序和注册顺序相反
atexit(fun1);
atexit(fun2);
atexit(fun3);
_exit(-1);
//abort(); //已放弃 (核心已转储): 非正常结束
//exit(-1); //自杀
printf("Hello World\n");
return 0; //寿终正寝
}