首页 > 代码库 > 学习笔记
学习笔记
Notes:
1、
/usr/lib:大部分的编译程序放在这个目录,在这里由编译时需要的可执行程序,还有一些特定版本的库文件与头文件。
/usr/bin/gcc:该目录指的是编译程序,即实际在命令中执行的程序。这个目录可供各个版本的gcc使用,只要用不同的编译程序目录来安装就可以。
/usr/include:这个目录及其子目录下包含程序所需要的头文件。缺少头文件,gcc在编译是会出现找不到头文件的错误。
2、gcc的工作过程 hello.c
预处理: gcc -E hello.c -o hello.i
编译阶段: gcc -S hello.i -o hello.s
汇编: gcc -c hello.i -o hello.o
链接: gcc hello.o -o hello
3、编译选项
-pedantic : 更加符合ANSI/ISO C的标准
-Wall / -Werror: 把警告信息也当作错误,减少发生错误的情况,使得写出的程序更加健壮。
4、可以借助Linux提供的time命令,大致统计出一个程序的运行时间
time ./hello
real: 进程总的执行时间,他和系统负载有关(包括了进程调度,切换的时间)
user: 被测量进程中用户指令的执行时间
sys: 被测来年该进程中内核带用户指令执行的时间,user和sys的和被称为CPU时间
5、说说优化 -O1(-O) -O2 -O3
优化可以给程序带来更好的执行性能,但在如下场合应该避免优化代码:
a:程序开发时,优化等级越高,消耗在编译上的时间越长,等到最后软件发行时再对最终生成的代码进行优化。
b:资源受限时,优化会增加可执行代码的体积。
c:跟踪调试时,优化会改写代码,不利于跟踪和调试。
6、在编译阶段使用管道来提高编译速度
gcc -pipe -Wall inefficient_code.c -o inefficient_code
7、在默认情况下,gcc在编译时不会将调试符号插入到生成的二进制代码中,因为会增加可执行文件的大小。
lz@starnight:~/code/basic$ gcc -pipe -Wall inefficient_code.c -o inefficient_code
inefficient_code.c: In function ‘main’:
inefficient_code.c:8:15: warning: variable ‘five’ set but not used [-Wunused-but-set-variable]
inefficient_code.c:7:20: warning: variable ‘temp’ set but not used [-Wunused-but-set-variable]
lz@starnight:~/code/basic$ ls -l inefficient_code
-rwxrwxr-x 1 lz lz 7172 11月 5 16:18 inefficient_code
lz@starnight:~/code/basic$ gcc -pipe -Wall inefficient_code.c -o inefficient_code -g
inefficient_code.c: In function ‘main’:
inefficient_code.c:8:15: warning: variable ‘five’ set but not used [-Wunused-but-set-variable]
inefficient_code.c:7:20: warning: variable ‘temp’ set but not used [-Wunused-but-set-variable]
lz@starnight:~/code/basic$ ls -l inefficient_code
-rwxrwxr-x 1 lz lz 8236 11月 5 16:19 inefficient_code
8、编译源代码不在同一个目录下
假设在当前目录下要编译test.c文件,而其中包含的一个头文件"myHeader.h"在/home/lz/code/basic/temp/head/目录中,
编译时需要加上 "-I"选项,下面时编译命令:
gcc -o test test.c -I /home/lz/code/basic/temp/head/
9、dgb调试
编译命令:gcc -ggdb3 hello.c -o hello
再使用命令:gdb hello, 进入调试
10、
drwxr-xr-x 3 lz lz 4096 11月 5 19:35 Downloads
-rw-r--r-- 1 lz lz 8445 11月 4 01:35 examples.desktop
lrwxrwxrwx 1 lz lz 43 11月 3 19:08 Link to 研一上 -> /media/包罗万象/USTC Learning/研一上
前十位:第1位表示文件类型,2-4位表示文件所有者权限,5-7位表示同组用户权限,8-10位表示其他用户组权限(读、写、执行)
文件类型:
-:普通文件 l:链接文件(link) c:字符设备文件(character) b:块设备文件(block)
s:套接字文件(socket) d:目录文件(directory) p:管道文件(pipe)
11、 stdin:0 stdout:1 stderr:2
一般来说,每个进程最多可以打开1024个文件(0-1023)
可以用命令来查看:ulimit -n
1024
12、重定向标准输出
command > filename #把标准输出重定向的文件filename中
command >> filename #以追加的方式将标准输出重定向到文件filename中
command l> filename #把标准输出重定向到一个文件中
> myfile #创建一个长度为0的空文件
13、查看文件的实际内容, -c表示以字符方式打印文件内容
lz@starnight:~/code/fileOps$ od -c test
0000000 a b c d e f g h i j \0 \0 \0 \0 \0 \0
0000020 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
*
0000060 \0 \0 0 1 2 3 4 5 6 7 8 9
0000074
14、改变文件的权限
lz@starnight:~/code/fileOps$ ll hello
-rwxr-xr-x 1 lz lz 27 11月 7 10:53 hello*
lz@starnight:~/code/fileOps$ chmod 0744 hello
lz@starnight:~/code/fileOps$ ll hello
-rwxr--r-- 1 lz lz 27 11月 7 10:53 hello*
lz@starnight:~/code/fileOps$ ./change_mode
Ok, change mode successfully.
lz@starnight:~/code/fileOps$ ll hello
-rwxr-xr-x 1 lz lz 27 11月 7 10:53 hello*
15、调用vfork()产生子进程,子进程运行结束后一定要调用exit()或者execve()退出。
16、使用exec函数族,一定要记得使用错误判断语句
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 execvpe(const char *file, char *const argv[], char *const envp[]);
其常见的错误有:
a.找不到文件或路径,此时errno被设置位ENOENT
b.数组argv和envp忘记使用NULL结束,此时errno被设置为EFAULT
c.没有对要执行文件的运行权限,此时errno被设置为EACCES
16、exit()和_exit()最大的区别在与,exit()函数在调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件;而_exit直接使进程停止运行,
清除其使用的内存空间,并销毁其在内核中的各种数据结构。
17、wait和waitpid
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
pid1 = wait(&status);
if( WIFEXITED(status) )
{
printf("the child process %d exit normally.\n", pid1);
printf("the return code is %d.\n", WEXITSTATUS(status));
}
学习笔记