校本教研网站建设方案,滴滴网站建设流程图,贵阳网站定制开发,建个网站花钱做百度推广目录
1.字符串函数
2.数据转换函数
3.格式化输入输出函数
4.权限控制函数
5.IO函数
6.进程控制函数
7.文件和目录函数 1.字符串函数 2.数据转换函数 3.格式化输入输出函数 #includestdarg.hvoid test(const char * format , ...){va_list ap;va_start(ap,format…目录
1.字符串函数
2.数据转换函数
3.格式化输入输出函数
4.权限控制函数
5.IO函数
6.进程控制函数
7.文件和目录函数 1.字符串函数 2.数据转换函数 3.格式化输入输出函数 #includestdarg.hvoid test(const char * format , ...){va_list ap;va_start(ap,format);vprintf(format,ap);char buffer[5000] ;va_start(ap,format);vsnprintf(buffer,sizeof (buffer) , format , ap ); va_start(ap,format);vsprintf(buffer , format,ap);}int main(){test(%s %d %f , bug , 20 , 20.145);} 4.权限控制函数 补充知识 #chmod
# 语法格式: chmod who [|-|] mod 文件名- who:- u: user - 文件所有者- g: group - 文件所属组用户- o: other - 其他- a: all, 以上是三类人 ugo- 对权限的操作:: 添加权限-: 去除权限: 权限的覆盖- mod: 权限r: read, 读w: write, 写x: execute, 执行-: 没有权限# 将文件所有者权限设置为读和执行, 也就是权限覆盖
robinOS:~/Linux$ chmod urx b.txt
robinOS:~/Linux$ ll b.txt
-r-xrw-r-- 2 robin robin 2929 Apr 14 18:53 b.txt*# 给其他人添加写和执行权限
robinOS:~/Linux$ chmod owx b.txt
robinOS:~/Linux$ ll b.txt
-r-xrw-rwx 2 robin robin 2929 Apr 14 18:53 b.txt*# 给文件所属组用户去掉读和执行权限
robinOS:~/Linux$ chmod g-rx b.txt
robinOS:~/Linux$ ll b.txt
-r-x-w-rwx 2 robin robin 2929 Apr 14 18:53 b.txt*# 将文件所有者,文件所属组用户,其他人权限设置为读写执行
robinOS:~/Linux$ chmod arwx b.txt
robinOS:~/Linux$ ll b.txt
-rwxrwxrwx 2 robin robin 2929 Apr 14 18:53 b.txt*# 语法格式: chmod [|-|] mod 文件名- 对权限的操作:: 添加权限-: 去除权限: 权限的覆盖, 等号可以不写- mod: 权限描述, 所有权限都放开是 7- 4: read, r- 2: write, w- 1: execute , x- 0: 没有权限# 分解: chmod 0567 a.txt0 5 6 7八进制 文件所有者 文件所属组用户 其他人r x r w rwx######################### 举例 #########################
# 查看文件 c.txt 的权限
robinOS:~/Linux$ ll c.txt
-rwxrwxrwx 2 robin robin 2929 Apr 14 18:53 c.txt*# 文件所有者去掉执行权限, 所属组用户去掉写权限, 其他人去掉读写权限
robinOS:~/Linux$ chmod -123 c.txt
robinOS:~/Linux$ ll c.txt
-rw-r-xr-- 2 robin robin 2929 Apr 14 18:53 c.txt*# 文件所有者添加执行权限, 所属组用户和其他人权限不变
robinOS:~/Linux$ chmod 100 c.txt
robinOS:~/Linux$ ll c.txt
-rwxr-xr-- 2 robin robin 2929 Apr 14 18:53 c.txt*# 将文件所有者,文件所属组用户,其他人权限设置为读写, 没有执行权限
robinOS:~/Linux$ chmod 666 c.txt
robinOS:~/Linux$ ll c.txt
-rw-rw-rw- 2 robin robin 2929 Apr 14 18:53 c.txt # 语法1-只修改所有者:
$ sudo chown 新的所有者 文件名# 语法2-同时修改所有者和所属组:
$ sudo chown 新的所有者:新的组名 文件名# 查看文件所有者b.txt 属于 robin 用户
robinOS:~/Linux$ ll b.txt
-rw-rw-rw- 2 robin robin 2929 Apr 14 18:53 b.txt# 将 b.txt 的所有者修改为 luffy
robinOS:~/Linux$ sudo chown luffy b.txt
[sudo] password for robin:
robinOS:~/Linux$ ll b.txt
-rw-rw-rw- 2 luffy robin 2929 Apr 14 18:53 b.txt# 修改文件所有者和文件所属组
# 查看文件所有者和所属组
robinOS:~/Linux$ ll b.txt
-rw-rw-rw- 2 luffy robin 2929 Apr 14 18:53 b.txt# 同时修改文件所有者和文件所属组
robinOS:~/Linux$ sudo chown robin:luffy b.txt
robinOS:~/Linux$ ll b.txt
-rw-rw-rw- 2 robin luffy 2929 Apr 14 18:53 b.txt # 只修改文件所属的组, 普通用户没有这个权限, 借助管理员的权限
# 语法: sudo chgrp 新的组 文件名# 查看文件所属组信息
robinOS:~/Linux$ ll b.txt
-rw-rw-rw- 2 robin luffy 2929 Apr 14 18:53 b.txt# 修改文件所属的组
robinOS:~/Linux$ sudo chgrp robin b.txt
robinOS:~/Linux$ ll b.txt
-rw-rw-rw- 2 robin robin 2929 Apr 14 18:53 b.txt 下面说一下文件设置用户ID位这个ID仅仅是一个二进制的bit位在文件stat结构的st_mode成员中对于一般的文件该位是置为无效的只有可执行文件的该位是置为有效的。 改变三个用户ID的方法 2. 什么时候用到设置用户id和设置组id 小实验 此时给上文件用户设置ID和文件设置组ID的权限s,此时执行时 特权用户使用这几个函数的时候都是直接用参数的值来设置实际用户ID或者有效用户ID这些值都可以是任意的。 例如setreuid(ruid, euid), 如果是特权用户则直接设置实际用户ID为ruid,有效用户ID为euid。
但非特权用户就不行了非特权用户用setuid()seteuid()则只能将有效有户ID设置为实际用户ID或保存的设置用户ID如果不是这两个数设置失败 此时我们改变一下文件的用户和用户组为zhz 创建会话ID
pid_t setsid(void) 守护进程的关键调用函数
1.用户和组要有足够的权限2.当前进程只能是子进程才能调用成功 5.IO函数 头文件
sys/types.h
sys/stat.h
fcntl.h 打开文件
int open(const char *pathname, int flags, mode_t mode) fcntl.h 测试代码
#include cstdio
#includeiostream
#includeunistd.h //头文件#includefcntl.h
#includesys/file.h
#includeerror.h //errno
#includestring.h //strerrorvoid f() {//int fd open(/home/zhz/text.txt, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);int fd open(/home/zhz/text.txt, O_RDWR | O_CREAT, 0755);//文件锁是一个建议性锁此时是无效上锁/*if (fd 0) { printf(write:%d\n, write(fd, hello, 5));printf(flock:%d\n, flock(fd, LOCK_EX));sleep(6);flock(fd, LOCK_UN);close(fd);}*/if (fd 0) {printf(flock:%d\n, flock(fd, LOCK_EX)); //先上锁在写你认为这有锁才起效果printf(write:%d\n, write(fd, hello, 5));sleep(6);flock(fd, LOCK_UN);close(fd);}else {std::cout strerror(errno) std::endl;}}
int main()
{f();return 0;
} 6.进程控制函数
exec函数族提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件并用它来取代原调用进程的数据段、代码段和堆栈段在执行完之后原调用进程的内容除了进程号外其他全部被新程序的内容替换了。
在Linux中使用exec函数族主要有以下两种情况
1.当进程认为自己不能再为系统和用户做出任何贡献时就可以调用任何exec 函数族让自己重生。
2.如果一个进程想执行另一个程序那么它就可以调用fork函数新建一个进程然后调用任何一个exec函数使子进程重生。 1参数传递方式exec函数族的参数传递有两种方式一种是逐个列举(l)的方式而另一种则是将所有参数整体构造成指针数组(v)进行传递。
在这里参数传递方式是以函数名的第5位字母来区分的字母为“l”list的表示逐个列举的方式字母为“v”vertor的表示将所有参数整体构造成指针数组传递然后将该数组的首地址当做参数传给它数组中的最后一个指针要求是NULL。读者可以观察execl、execle、execlp的语法与execv、execve、execvp的区别。 2.环境变量exec函数族使用了系统默认的环境变量也可以传入指定的环境变量。这里以“e”environment结尾的两个函数execle、execve就可以在envp[]中指定当前进程所使用的环境变量替换掉该进程继承的环境变量。 3.PATH环境变量说明 PATH环境变量包含了一张目录表系统通过PATH环境变量定义的路径搜索执行码PATH环境变量定义时目录之间需用用“:”分隔以“.”号表示结束。PATH环境变量定义在用户的.profile或.bash_profile中下面是PATH环境变量定义的样例此PATH变量指定在“/bin”、“/usr/bin”和当前目录三个目录进行搜索执行码。
PATH/bin:/usr/bin:.
export $PATH 4.进程中的环境变量说明 在Linux中Shell进程是所有执行码的父进程。当一个执行码执行时Shell进程会fork子进程然后调用exec函数去执行执行码。Shell进程堆栈中存放着该用户下的所有环境变量使用execl、execv、execlp、execvp函数使执行码重生时Shell进程会将所有环境变量复制给生成的新进程而使用execle、execve时新进程不继承任何Shell进程的环境变量而由envp[]数组自行设置环境变量。 void f() {pid_t pid fork();if (pid 0) {//这是父进程sleep(5);std::cout parent!!!! std::endl;}else {execl(/bin/ls, ls, -l, NULL);}
} 进程的数量是有限的
#includeassert.h C/C assert()函数用法总结 - 白菜菜白 - 博客园 (cnblogs.com) (9条消息) 多进程之进程退出函数exit_exit,atexit详解_c语言 exit() atexit_谢永奇1的博客-CSDN博客 (9条消息) on_exit()函数使用说明_Ahren.zhao的博客-CSDN博客 #include cstdio
#includeiostream
#includeunistd.h //头文件#includefcntl.h
#includesys/file.h
#includeerror.h //errno
#includestring.h //strerror
#includeassert.hvoid fa() {printf(father is over\n);
}void son(int status , void * str) {printf(%d %s\n, status , (char *)str);}
void pra() {pid_t pid fork();if (pid 0) {atexit(fa);std::cout parent!!!! std::endl;exit(0);}else {char s[10] i am son;char* str s[0];on_exit(son, str );exit(0);}
}
int main()
{pra();return 0;
} #include cstdio
#includeiostream
#includeunistd.h //头文件#includefcntl.h
#includesys/file.h
#includeerror.h //errno
#includestring.h //strerror
#includeassert.h#includesetjmp.h
#includesignal.h
jmp_buf jmpbuf; //用来存储寄存器的信息void test002() {//to do somethingslongjmp(jmpbuf, 1); //此时程序发生错误1
}void test001() {//to do somethings//...test002();
}void signal_deal(int sig) { //注册信号处理函数if (sig SIGSEGV) {longjmp(jmpbuf, SIGSEGV);}}void pra() {signal(SIGSEGV,signal_deal); //异常捕获int ret setjmp(jmpbuf); //保存所有寄存器的值if (ret 0) { //c语言处理异常的一种机制test001();*(int*)(NULL) 0; //段错误}else if (ret 1) {printf(error 1\n);}else if (ret SIGSEGV) {printf(error SIGSEGV\n);}
}int main()
{pra();return 0;
} 当注释掉test001()时此时引发段错误信号进入异常捕获处理函数。 知识补充
信号是进程在运行过程中由自身产生或由进程外部发过来的消息。
信号是硬件中断的软件模拟(软中断)。每个信号用一个整型常量宏表示以SIG开头比如SIGCHLD、SIGINT等它们在系统头文件中signal.h定义。
由进程的某个操作产生的信号称为同步信号(synchronous signals),例如除0由用户击键之类的进程外部事件产生的信号叫做异步信号。(asynchronous signals)。 signal
C 库函数 void (*signal(int sig, void (*func)(int)))(int) 设置一个函数来处理信号即带有 sig 参数的信号处理程序。 进程接收到信号以后可以有如下3种选择进行处理
1. 接收默认处理接收默认处理的进程通常会导致进程本身消亡。例如连接到终端的进程用户按下CTRLc将导致内核向进程发送一个SIGINT的信号进程如果不对该信号做特殊的处理系统将采用默认的方式处理该信号即终止进程的执行
2.忽略信号进程可以通过代码显示地忽略某个信号的处理例如signal(SIGINT,SIGDEF)但是某些信号是不能被忽略的
#include stdio.h
#include unistd.h
#include stdlib.h
#include signal.hvoid sighandler(int);int main()
{signal(SIGINT, sighandler);while(1) {printf(开始休眠一秒钟...\n);sleep(1);}return(0);
}void sighandler(int signum)
{printf(捕获信号 %d跳出...\n, signum);exit(1);
}让我们编译并运行上面的程序这将产生以下结果且程序会进入无限循环需使用 CTRL C 键跳出程序。 3.捕捉信号并处理进程可以事先注册信号处理函数当接收到信号时由信号处理函数自动捕捉并且处理信号。
有两个信号既不能被忽略也不能被捕捉它们是SIGKILL和SIGSTOP。即进程接收到这两个信号后只能接受系统的默认处理即终止线程。 which的取值根据who来选择,一般关注进程优先级
PRIO_PROCESS PRIO_PGRP PRIO_USER #include cstdio
#includeiostream
#includeunistd.h //头文件#includefcntl.h
#includesys/file.h
#includeerror.h //errno
#includestring.h //strerror
#includeassert.h
#includesetjmp.h
#includesignal.h#includestdlib.hvoid pra(){int ret system(ls -l);printf(system return : %d\n, ret);ret system(mkdir test);printf(system return : %d\n, ret);char buffer[512] ;snprintf(buffer, sizeof buffer, echo \%s\test/test.txt, __FUNCTION__);//组合使用可以进行批处理printf(%s\n, buffer);ret system(buffer);printf(system return : %d\n, ret);
}int main() {pra();return 0;
} 补充知识: 7.文件和目录函数 总结open与fopen的区别 - NickyYe - 博客园 (cnblogs.com) 实现文件输出重定向 void pra1() {FILE* pFile fopen(./test.txt, r);if (pFile ! NULL) {//char buffer[4096] 栈上申请的buffer不要超过64kchar* buffer new char[1024*10]; //单词内存分配最好不要超过2Gmemset(buffer, 0 , 1024 * 10);size_t ret fread(buffer, 1, 1024, pFile);printf(num : %d %s \n, ret,buffer);fclose(pFile);}else {printf(open error\n);}}void pra() {FILE* pFile fopen(./test.txt, r);if (pFile ! NULL) {char* buffer new char[1024*10]; //单词内存分配最好不要超过2Gprintf(%s(%d):%s [%c]\n, __FILE__, __LINE__, __FUNCTION__,fgetc(pFile));printf(%s(%d):%s [%s]\n, __FILE__, __LINE__, __FUNCTION__, fgets(buffer,1024*10 ,pFile));printf([%d]\n, fgetc(pFile));fclose(pFile);}else {printf(open error\n);}} 每次读写都会改变文件中位值的指针记录 while(!feof(pFile)){bzero(buffer,sizeof buffer);fgets(buffer,sizeof buffer,pFile);
} int ret 0;ret mkdir( he , 755);std::cout ret std::endl; int ret 0;
//ret mkdir( he , 755);
remove(he);
std::cout ret std::endl; 递归遍历目录