`

linux程序设计第四版的一些笔记

 
阅读更多

 

标准的系统库经常放在 /lib 和/usr/lib 下面。

库的名字命名是有规范的

以lib开头,静态库的结尾是.a ,共享库的结尾是.so

 

位于 /usr/lib/libm.a 就是系统的一个数据函数库

通过下面的命令 -l选项来告诉c编译器函数库的位置 m 是libm.a的缩写

$ gcc -o fred fred.c -lm 

 

如果我们的库没有放在/lib 和/user/lib目录下面,那么我们需要通过-L选择来告诉编译器我们的库的位置

$ gcc -o x11fred -L/usr/openwin/lib x11fred.c -lX11

 

编写并运行c程序的步骤

1、 编写c源代码

2、将我们写的.c后缀的源文件编译成.o的文件

gcc -c bill.c fred.c 

gcc -c program.c

3、将.o的文件链接成可执行的文件

gcc -o program grogram.o bill.o

4、运行我们写好的程序

./program

 

5 用ar命令来打包我们自己的库函数 ,将bill.o fred.o打成一个包

$ar crv libfoo.a bill.o fred.o

 

就可以通过连接库的方式来编译我们的程序了

$ gcc -o program program.o libfoo.a

也可以通过下面的方式

$ gcc –o program program.o –L. –lfoo

-L 告诉c编译器我们的库函数查找位置为当前目录,库函数的名字叫libfoo.a

 

我们有时候想查看我们的程序用到了哪些共享库,我们可以通过ldd(loader dynamic lib)

$ ldd program

 

对文件操作的API

 

#include <stdio.h>

FILE *fopen(const char *filename, const char *mode);

 

mode的取值可以为:

“r”or “rb”: Open for reading only

“w”or “wb”: Open for writing, truncate to zero length

“a”or “ab”: Open for writing, append to end of file

“r+”or “rb+”or “r+b”: Open for update (reading and writing)

“w+”or “wb+”or “w+b”: Open for update, truncate to zero length

“a+”or “ab+”or “a+b”: Open for update, append to end of file

 

如果打开成功,返回FILE* 类型的指针,如果失败,则返回NULL

 

#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

 

这个函数用来从文件流中读取数据到给定的数据缓存区中ptr。fread,fwrite都是处理records,size指定的是一个record的大小。nitems指定的是要读取的记录的数目,

返回的是实际读取到缓存区中记录的数据

 

#include <stdio.h>

size_t fwrite (const void *ptr, size_t size, size_t nitems, FILE *stream);

和fread的语法是类似的,只不过他是将缓存区中的数据写到文件流中,

 

#include <stdio.h>

int fclose(FILE *stream);

用fclose函数是为了确保文件流中的数据已经写完了。

 

#include <stdio.h>

int fflush(FILE *stream);

 

调用fclose的时候就显示的调用fflush函数

 

#include <stdio.h>

int fseek(FILE *stream, long int offset, int whence);

 

#include <stdio.h>

int fgetc(FILE *stream);

int getc(FILE *stream);

int getchar();

 

getchar是和getc(stdin)等价的,从标准的输入设备中读取一个字符

 

#include <stdio.h>

int fputc(int c, FILE *stream);

int putc(int c, FILE *stream);

int putchar(int c);

 

上面的都是读取一共字符,下面的是读取一个字符串

 

#include <stdio.h>

char *fgets(char *s, int n, FILE *stream);

char *gets(char *s);

 

#include <stdio.h>

int printf(const char *format, ...);

int sprintf(char *s, const char *format, ...);

int fprintf(FILE *stream, const char *format, ...);

 

printf 是输出道标准的输入设备,fprintf是输出到指定的文件流,而sprintf输出到一个字符串 s。

 

#include <stdio.h>

int scanf(const char *format, ...); 

int fscanf(FILE *stream, const char *format, ...); 

int sscanf(const char *s, const char *format, ...);

 

fgetpos: Get the current position in a file stream.

fsetpos: Set the current position in a file stream.

ftell: Return the current file offset in a stream.

rewind: Reset the file position in a stream.

freopen: Reuse a file stream.

 

简单的一共文件复制的例子

 

#include<stdio.h>

#include<stdlib.h>

 

int main()

{

 

int c;

FILE *in,*out;

 

in = fopen("file.in","r");

out = fwrite("file.out","w");

//一次读取一个字符

while((c=fgetc(in))!=EOF)

{

fputc(c,out);

}

//正常退出

exit(0);

}

 

#include <errno.h>

extern int errno;

当函数执行失败的时候,errno才是有效的。我们需要保存这个值到一耳光变量中取,因为其他的任何函数都可以改变这个errno。

 

#include <stdio.h>

int ferror(FILE *stream);

int feof(FILE *stream);

void clearerr(FILE *stream);

 

ferror函数用来测试文件流是否出现错误,如果是就返回非0,否则返回0

 

feof 函数用来测试文件是否到了末尾,如果是就返回非0,否则返回0

if(feof(stream))

{

printf("at the end of file");

}

 

#include <stdio.h>

int fileno(FILE *stream);

FILE *fdopen(int fildes, const char *mode);

 

 

对文件和目录的维护

 

chmod 改变文件的读,写权限

#include <sys/stat.h>

int chmod(const char *path, mode_t mode);

 

chown 改变一个文件的所有者,所属组

#include <sys/types.h>

#include <unistd.h>

int chown(const char *path, uid_t owner, gid_t group);

 

建立目录

#include <sys/types.h>

#include <sys/stat.h>

int mkdir(const char *path, mode_t mode);

 

删除目录

#include <unistd.h>

int rmdir(const char *path);

 

改变目录

#include <unistd.h>

int chdir(const char *path);

 

获取当前的目录名到buf中

#include <unistd.h>

char *getcwd(char *buf, size_t size);

 

打开目录

#include <sys/types.h>

#include <dirent.h>

DIR *opendir(const char *name);

 

读取目录中的内容

 

#include <sys/types.h>

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

 

dirent包含了 ino_t  d_ino: 文件的i节点值,char d_name[] 文件的名字

 

#include <sys/types.h>

#include <dirent.h>

long int telldir(DIR *dirp);

 

telldir返回的是记录在文件流中的当前位置的值。

 

设置目录实体指针在文件流(dirp)中的位置,loc用来设置位置

#include <sys/types.h>

#include <dirent.h>

void seekdir(DIR *dirp, long int loc);

 

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

 

下面是一个目录扫描的程序

 

#include <unistd.h>

#include <stdio.h>

#include <dirent.h>

#include <string.h>

#include <sys/stat.h>

#include <stdlib.h>

void printdir(char *dir, int depth)

{

 

DIR *dp;

struct dirent *entry;

struct stat statbuf;

if((dp = opendir(dir)) == NULL) {

fprintf(stderr,”cannot open directory: %s\n”, dir);

 

}

chdir(dir);

while((entry = readdir(dp)) != NULL) {

lstat(entry->d_name,&statbuf);

if(S_ISDIR(statbuf.st_mode)) {

/* Found a directory, but ignore . and .. */

if(strcmp(“.”,entry->d_name) == 0 || 

strcmp(“..”,entry->d_name) == 0)

continue;

printf(“%*s%s/\n”,depth,”“,entry->d_name);

/* Recurse at a new indent level */

printdir(entry->d_name,depth+4);

}

else printf(“%*s%s\n”,depth,”“,entry->d_name);

}

chdir(“..”);

closedir(dp);

}

 

int main()

{

printf(“Directory scan of /home:\n”);

printdir(“/home”,0);

printf(“done.\n”);

exit(0);

}

 

#include <unistd.h>

int getopt(int argc, char *const argv[], const char *optstring); 

extern char *optarg; 

extern int optind, opterr, optopt;

用来解析程序传进来的参数和可选项

 

1、如果可选项是带有一个值,则这个值放到了optarg这个变量中

2、如果return -1 ,表明没有可选项要处理了,这里有个特殊的选项那就是--,它就会让

getopt停止扫描可选项

3、如果可选择输入了不是我们定义的-i,-j 则会返回?

4、如果可选项要求需要值,而调用的时候没有传递值,则会返回?:,这个值可以通过传替一个字符替换。下面的“:if:lr”中的第一个冒号就是用来替换的。

 

optwin是记录下一个要 处理参数的索引值

下面是一个具体的例子

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

int main(int argc, char *argv[])

{

int opt;

while((opt = getopt(argc, argv, “:if:lr”)) != -1) {

switch(opt) {

case ‘i’:

case ‘l’:

case ‘r’:

printf(“option: %c\n”, opt);

break;

case ‘f’:

printf(“filename: %s\n”, optarg);

break;

case ‘:’:

printf(“option needs a value\n”);

break;

case ‘?’:

printf(“unknown option: %c\n”, optopt);

break;

}

}

for(; optind < argc; optind++)

printf(“argument: %s\n”, argv[optind]);

exit(0);

}

 

 

设置环境变量

 

#include <stdlib.h>

char *getenv(const char *name);

int putenv(const char *string);

 

下面是一个利用getenv ,putenv的例子程序

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

int main(int argc, char *argv[])

{

char *var, *value;

if(argc == 1 || argc > 3) {

fprintf(stderr,”usage: environ var [value]\n”);

exit(1);

}

 

var = argv[1];

value = getenv(var);

if(value)

printf(“Variable %s has value %s\n”, var, value);

else

printf(“Variable %s has no value\n”, var);

 

if(argc == 3) {

char *string;

value = argv[2];

string = malloc(strlen(var)+strlen(value)+2);

if(!string) {

fprintf(stderr,”out of memory\n”);

exit(1);

}

strcpy(string,var);

strcat(string,”=”);

strcat(string,value);

printf(“Calling putenv with: %s\n”,string);

if(putenv(string) != 0) {

fprintf(stderr,”putenv failed\n”);

free(string);

exit(1);

}

value = getenv(var);

if(value)

printf(“New value of %s is %s\n”, var, value);

else

printf(“New value of %s is null??\n”, var);

}

exit(0);

}

 

 

操作时间的函数

 

#include <time.h>

struct tm *gmtime(const time_t timeval);

 

这个函数返回的时间是UTC时间,为了同步世界时间

tm Member Description

int tm_sec Seconds, 0-61

int tm_min Minutes, 0-59

int tm_hour Hours, 0-23

int tm_mday Day in the month, 1-31

int tm_mon Month in the year, 0-11 (January = 0)

int tm_year Years since 1900

int tm_wday Day in the week, 0-6 (Sunday = 0)

int tm_yday Day in the year, 0-365

 

 

#include <time.h>

#include <stdio.h>

#include <stdlib.h>

int main()

{

struct tm *tm_ptr;

time_t the_time;

(void) time(&the_time);

tm_ptr = gmtime(&the_time);

printf(“Raw time is %ld\n”, the_time);

printf(“gmtime gives:\n”);

printf(“date: %02d/%02d/%02d\n”, 

tm_ptr->tm_year, tm_ptr->tm_mon+1, tm_ptr->tm_mday);

printf(“time: %02d:%02d:%02d\n”,

tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);

exit(0);

}

 

下面是获取本地的时间

#include <time.h>

struct tm *localtime(const time_t *timeval);

 

将日期结构体转换成时间戳

#include <time.h>

time_t mktime(struct tm *timeptr);

 

格式化日期成size_t类型

#include <time.h>

size_t strftime(char *s, size_t maxsize, const char *format, struct tm *timeptr);

 

格式化日期成一个字符串

#include <time.h>

char *strptime(const char *buf, const char *format, struct tm *timeptr);

 

常用的时间格式 format 

“%a %b %d %H:%M:%S %Y”

 

下面是日期转成字符串的例子

 

#include <time.h>

#include <stdio.h>

#include <stdlib.h>

int main()

{

struct tm *tm_ptr, timestruct;

time_t the_time;

char buf[256];

char *result;

(void) time(&the_time);

tm_ptr = localtime(&the_time);

strftime(buf, 256, “%A %d %B, %I:%S %p”, tm_ptr);

printf(“strftime gives: %s\n”, buf);

strcpy(buf,”Thu 26 July 2007, 17:53 will do fine”);

printf(“calling strptime with: %s\n”, buf);

tm_ptr = &timestruct;

result = strptime(buf,”%a %d %b %Y, %R”, tm_ptr);

printf(“strptime consumed up to: %s\n”, result);

printf(“strptime gives:\n”);

printf(“date: %02d/%02d/%02d\n”, 

tm_ptr->tm_year % 100, tm_ptr->tm_mon+1, tm_ptr->tm_mday);

printf(“time: %02d:%02d\n”,

tm_ptr->tm_hour, tm_ptr->tm_min);

exit(0);

}

 

getuid获取用户的id

#include <sys/types.h>

#include <unistd.h>

uid_t getuid(void);

char *getlogin(void);

 

获取密码的详细信息

 

#include <sys/types.h>

#include <pwd.h>

 

struct passwd *getpwuid(uid_t uid);

struct passwd *getpwnam(const char *name);

 

char *pw_name The user’s login name

uid_t pw_uid The UID number

gid_t pw_gid The GID number

char *pw_dir The user’s home directory

char *pw_gecos The user’s full name

char *pw_shell The user’s default shell

 

下面是一个获取当前登录用户信息的程序

#include <sys/types.h>

#include <pwd.h>

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

int main()

{

uid_t uid;

gid_t gid;

struct passwd *pw;

uid = getuid();

gid = getgid();

printf(“User is %s\n”, getlogin());

printf(“User IDs: uid=%d, gid=%d\n”, uid, gid);

 

pw = getpwuid(uid);

printf(“UID passwd entry:\n name=%s, uid=%d, gid=%d, home=%s, shell=%s\n”,

pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);

pw = getpwnam(“root”);

printf(“root passwd entry:\n”);

printf(“name=%s, uid=%d, gid=%d, home=%s, shell=%s\n”,

pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);

exit(0);

}

 

查看系统日志信息

 

#include <syslog.h>

void syslog(int priority, const char *message, arguments...);

 

Priority Level Description

LOG_EMERG An emergency situation

LOG_ALERT High-priority problem, such as database corruption

LOG_CRIT Critical error, such as hardware failure

LOG_ERR Errors

LOG_WARNING Warning

LOG_NOTICE Special conditions requiring attention

LOG_INFO Informational messages

LOG_DEBUG Debug messages

 

#include <syslog.h>

#include <stdio.h>

#include <stdlib.h>

int main()

{

FILE *f;

f = fopen(“not_here”,”r”);

if(!f)

syslog(LOG_ERR|LOG_USER,”oops - %m\n”);

exit(0);

}

 

 

宁外一个增强的日记操作函数

 

#include <syslog.h>

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

int main()

{

int logmask;

openlog(“logmask”, LOG_PID|LOG_CONS, LOG_USER);

syslog(LOG_INFO,”informative message, pid = %d”, getpid());

syslog(LOG_DEBUG,”debug message, should appear”);

logmask = setlogmask(LOG_UPTO(LOG_NOTICE));

syslog(LOG_DEBUG,”debug message, should not appear”);

exit(0);

}

 

mysql 接口

 

设置mysql的日志存放位置,数据库的引擎,字符编码

vi /etc/my.cnf

 

设置密码

1、mysqladmin -u root password newpassword

这种方式是不安全的,因为其他的人可以通过ps命令查看,也可以通过history

 

2、进入mysql设置密码

>mysql -u root

>user mysql;

>SET password=PASSWORD('root');

 

删除安装时候mysql自动创建的用户

 

1、首先查看当前的用户

SELECT user, host, password FROM user;

 

2、删除没有用到的用户

 

DELETE FROM user WHERE user != ‘root’;

DELETE FROM user WHERE host != ‘localhost’;

 

让rick只可以通过localhost登录

GRANT ALL ON *.* TO rick@localhost IDENTIFIED BY ‘secretpassword';

让rick可以通过子网掩码为192.168.0.0 网络号为255.255.0.0的登录

 GRANT ALL ON *.* TO rick@'192.168.0.0/255.255.255.0' IDENTIFIED BY '123456';

让nick可以通过wiley.com访问

 GRANT ALL ON *.* TO rick@'%.wiley.com' IDENTIFIED BY '123456';

 

 

mysql

mysql的命令行工具

连接mysql服务器

mysql -u rick -p foo

以非交互模式执行sql命令,通过从文件中读取命令,foo是数据库

$mysql -u rick --password=secretpassword foo < sqlcommands.sql

mysqladmin

可以通过

$mysqladmin --help 来查看mysqladmin的一些命令信息

mysqlbug

给开发者和管理员调试mysql服务器的一种工具

$mysqlbug --help

 

mysqldump

用来导入或者导出mysql数据

$mysqldump --help

 mysqldump -u rick -p myplaydb > myplaydb.dump

 

 mysqlimport

 用来一次导入大量的数据到某个表中

 

grant <privilege> on <object> to <user> [identified by user-password] [with grant option];

 

alter Alter tables and indexes.

create | Create databases and tables. 

delete | Delete data from the database.

drop   | Remove databases and tables.

index  | Manage indexes.

insert | Add data to the database.

lock tables | Allow locking of tables.

select | Retrieve data.

update | Modify data.

all All| the above.

 

object的格式 :databasename.tablename

 

foo.* 表示foo数据库下面所有的表

 

收回权限

revoke <a_privilege> on <an_object> from <a_user>

 

删除用户

mysql> use mysql

mysql> DELETE FROM user WHERE user = “rick”

mysql> FLUSH PRIVILEGES;

 

查看mysql安装的位置

先用rpm -qa \*mysql\*看看你安装了哪些包,然后用 rpm -ql xxxxxxx 去查看具体的包安装位置

 

#include <mysql.h>

MYSQL *mysql_init(MYSQL *);

 

在这个是用来初始化mysql连接,通常参数传递的是NULL

 

返回值给下面的mysql_real_connect(MYSQL *conn)

 

MYSQL *mysql_real_connect(MYSQL *connection,

const char *server_host,

const char *sql_user_name,

const char *sql_password,

const char *db_name,

unsigned int port_number,

const char *unix_socket_name, 

unsigned int flags);

 

这里需要说明的是后面3个参数的取值

一般设置成 0,NULL,0 如果你的端口是用的mysql默认的端口3306

 

关闭mysql连接,释放占用的系统资源

void mysql_close(MYSQL *connection);

 

int mysql_options(MYSQL *connection, enum option_to_set,

const char *argument);

 

MYSQL_OPT_CONNECT_TIMEOUT  const unsigned int *  The number of seconds to wait

before timing out a connection.

MYSQL_OPT_COMPRESS None, use NULL Use compression   on the network connection.

MYSQL_INIT_COMMAND const char *      Command to send each time a connection is established

 

错误处理

 

1、下面的报的是客户端的常见错误

unsigned int mysql_errno(MYSQL *connection);

 

2、返回的是与服务器规范定义的相关错误

char *mysql_error(MYSQL *connection);

 

执行查询

int mysql_query(MYSQL *connection, const char *query)

 

处理返回的结果

 

my_ulonglong mysql_affected_rows(MYSQL *connection);

返回的上面UPDATE,INSERT,DELETE query影响的记录数

 

#include <stdlib.h>

#include "mysql.h"

 

int main(int argc,char * argv[])

{

        MYSQL *conn;

        int result;

        conn =  mysql_init(NULL);

        conn = mysql_real_connect(conn,"localhost","rick","secret","foo",0,NULL,0);

        if(conn){

                printf("connection success\n");

                /*执行对数据库的CRUD*/;

                char * sql = "insert into children(fname,age) values('anna',33)";

                result = mysql_query(conn,sql);

                if(!result) {

                /*非0说明操作成功,打印出影响的记录数据*/

                printf("insert %lu rows\n",(unsigned long)mysql_affected_rows(conn));

                mysql_close(conn);

        }

        else{

                printf("connection fail,%d,%s",mysql_errno(conn),mysql_errno(conn));

        }

        return EXIT_SUCCESS;

}

 

mysql接口

 

 LAST_INSERT_ID()

 获取最进插进去的id

 SELECT LAST_INSERT_ID();

 

Just as you did with the INSERTand DELETEstatements, you’ll use mysql_queryto send the SQL. Next you’ll retrieve the data using either mysql_store_resultor mysql_use_result, depending on how you want the data retrieved. Next you’ll use a sequence of mysql_fetch_rowcalls to process the data. Finally,you’ll use mysql_free_resultto clear the memory you used for your query. 

The difference between mysql_use_resultand mysql_store_resultbasically amounts to whether you want to get your data back a row at a time, or get the whole result set in one go. The latter is more appropriate in circumstances where you anticipate a smaller result set.

 

存储所有返回给客户端的数据

MYSQL_RES *mysql_store_result(MYSQL *connection);

 

获取返回的记录数

long mysql_num_rows(MYSQL_RES *result);

 

获取某一行数据

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

 

让行记录的指针跳转到指定的offset位置,offset在0-num_record ,不包括num_record

 

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);

 

告诉当前行记录指针的位置

MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);

移动当前记录指针的位置,同事返回上次记录指针的位置

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);

 

检索一行一行的数据

MYSQL_RES *mysql_use_result(MYSQL *connection);

 

获取具体某个字段的值

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);

unsigned int mysql_field_count(MYSQL *connection);

释放资源

void mysql_free_result(MYSQL_RES *result);

 

int mysql_select_db(MYSQL *connection, const char *dbname);

int mysql_shutdown(MYSQL *connection, enum mysql_enum_shutdown_level);

 

 

 

下面是一个完整的例子

 

#include <stdlib.h>

#include <stdio.h>

#include “mysql.h”

MYSQL my_connection;

MYSQL_RES *res_ptr;

MYSQL_ROW sqlrow;

 

void display_header() {

MYSQL_FIELD *field_ptr;

printf(“Column details:\n”);

while ((field_ptr = mysql_fetch_field(res_ptr)) != NULL) {

printf(“\t Name: %s\n”, field_ptr->name);

printf(“\t Type: “);

if (IS_NUM(field_ptr->type)) {

printf(“Numeric field\n”);

} else {

switch(field_ptr->type) {

case FIELD_TYPE_VAR_STRING:

printf(“VARCHAR\n”);

break;

case FIELD_TYPE_LONG: 

printf(“LONG\n”);

break;

default:

printf(“Type is %d, check in mysql_com.h\n”, field_ptr->type);

} /* switch */

} /* else */

printf(“\t Max width %ld\n”, field_ptr->length);

if (field_ptr->flags & AUTO_INCREMENT_FLAG) 

printf(“\t Auto increments\n”);

printf(“\n”);

} /* while */

}

 

void display_row() {

unsigned int field_count;

field_count = 0;

while (field_count < mysql_field_count(&my_connection)) {

if (sqlrow[field_count]) 

printf(“%s “, sqlrow[field_count]);

else 

printf(“NULL”);

field_count++;

}

printf(“\n”);

}

 

int main(int argc, char *argv[]) {

int res;

mysql_init(&my_connection); 

if (mysql_real_connect(&my_connection, “localhost”, “rick”, 

“secret”, “foo”, 0, NULL, 0)) {

printf(“Connection success\n”);

res = mysql_query(&my_connection, “SELECT childno, fname, 

age FROM children WHERE age > 5”);

if (res) {

printf(“SELECT error: %s\n”, mysql_error(&my_connection));

} else {

res_ptr = mysql_store_result(&my_connection);

if (res_ptr) {

printf(“Retrieved %lu rows\n”, (unsigned long)mysql_num_rows(res_ptr));

while ((sqlrow = mysql_fetch_row(res_ptr))) {

printf(“Fetched data...\n”);

}

if (mysql_errno(&my_connection)) {

fprintf(stderr, “Retrive error: %s\n”, mysql_error(&my_connection)); 

}

mysql_free_result(res_ptr);

}

}

mysql_close(&my_connection);

} else {

fprintf(stderr, “Connection failed\n”);

if (mysql_errno(&my_connection)) {

fprintf(stderr, “Connection error %d: %s\n”,

mysql_errno(&my_connection), mysql_error(&my_connection));

}

}

return EXIT_SUCCESS;

 

}

 

 

Make 语法

 

target: fil1.c file2.o

gcc -o myapp file2.o

 

1、Target

target是自己定义的一些任务,其中如果make指定target,则会自动找第一个target

一般的程度都定义一个all的target,这样当用户没有指定target的时候就会自动执行我们定义的target。

all: myapp myapp.1

 

2、Dependencies

依赖指定他们在应用中各源文件的关系。

myapp: main.o 2.o 3.o

main.o: main.c a.h

2.o: 2.c a.h b.h

3.o: 3.c b.h c.h

上面的一个例子就是 myapp的target 依赖main.o 2.o 3.o这3个target,当这3个中任何一个更新了,那么myapp会自动重新编译,这是通过make自身的机制实现的,这也是我们为什么使用make的原因

 

3、Rules

规则制定了怎么样去创建target

规则一般是由一些的命令组成的

myapp: main.o 2.o 3.o

gcc -o myapp main.o 2.o 3.o

main.o: main.c a.h

gcc -c main.c

2.o: 2.c a.h b.h

gcc -c 2.c

3.o: 3.c b.h c.h

gcc -c 3.c

 

 

make文件中的注释用 #表示

 

Macros in a Makefile

# Which compiler

CC = gcc

宏是通过键值对的形式

引用改变量的时候可以通过$CC,${CC},$(CC),3种不同的形式,根据linux支持版本不一样

内置的宏 

 

Macro Definition

$? List of prerequisites (files the target depends on) changed more recently

than the current target

$@ Name of the current target

$< Name of the current prerequisite

$* Name of the current prerequisite, without any suffix

 

- 横线表示不管出现的错误,程序继续执行

@ 让make在执行命令之前不要打印命令的到标准的输出设备

 

可以使用make -p 来查看当前系统内置的规则

 

 

版本控制

 

通过rcs命令来初始化RCS对文件的控制

$ rcs -i important.c

 

通过ci 来查看当前的版本

$ ci important.c

 

check out 文件

$ co -l important.c

获取1.1那个版本文件

$ co -r1.1 important.c

check in 文件

$ ci important.c

$ ci -r2 important.c

查看文件的摘要信息

$ rlog important.c

 

比较2个文件的不同

$ rcsdiff -r1.1 -r1.2 important.c

 

 

CVS Subversion

cvs –d /usr/local/repository init svnadmin create /usr/local/repository

cvs import wrox/chap9-cvs svn import cvs-sp file:///usr/local/repository/trunk

cvs checkout wrox/chap9-cvs svn checkout file:///usr/local/repository/trunk cvs-sp

cvs diff svn diff

cvs rdiff svn diff tag1 tag2

cvs update svn status -u

cvs commit svn commit


分享到:
评论

相关推荐

    linux驱动程序设计学习笔记

    Linux驱动程序设计是嵌入式系统和服务器领域中不可或缺的一部分,它涉及到操作系统与硬件设备之间的交互,使得硬件功能能够被操作系统和用户空间程序所使用。本笔记基于《Linux设备驱动程序》第三版,该书是Linux...

    《Linux内核设计与实现》 第一章 读书笔记 Linux内核简介

    《Linux内核设计与实现》 第一章 读书笔记 Linux内核简介 面试被怼了Linux内核,于是决定好好看一下这本书。作为经典书籍,Linux内核设计与实现是一本很重要的书籍。在大学本科的课程中已经学习过有关操作系统的内容...

    《Python 3程序设计基础》读书笔记模板.pptx

    Python 3程序设计基础第四章:输入输出文件 * 输入输出:Python中可以使用多种方式进行输入输出,包括标准输入输出、文件输入输出等。 * 文件操作:Python中可以使用多种方式进行文件操作,包括读取、写入、追加等...

    嵌入式linux开发基础笔记

    嵌入式Linux开发是当前IT领域的一个重要分支,它涉及到硬件、操作系统、驱动程序、应用程序等多个层面的综合技术。在本笔记中,我们将深入探讨嵌入式Linux开发的基础知识,帮助IT开发者更好地理解和掌握这一技术。 ...

    Linux操作系统学习笔记整理.docx

    ### Linux操作系统学习笔记知识点 #### 一、Linux简介 **1.1 定义与特点** - **定义**: Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统。 - **创始人**: 林纳斯·本纳第克特·托瓦兹(Linus ...

    Linux网络编程全接笔记

    ### Linux网络编程全接触笔记详解 #### 一、分层模型结构 1. **OSI 7层模型**:这是国际标准化组织(ISO)提出的一个网络分层模型,旨在为不同厂商之间的网络设备提供标准接口。它从下往上依次分为: - **物理层*...

    python核心笔记.pdf

    【第三章 Python基础】和【第四章 Python对象】详细阐述了Python的基础语法,包括变量、数据类型、操作符、控制结构等。Python中的基础数据类型如数字(【第五章】)、序列(如字符串、列表和元组,【第六章】)、...

    《笨方法学python》所有练习程序及笔记

    以上文件为《笨方法学python》第四版所有练习的程序,都是自己一点点写的并全部通过正确运行,除了书中已给出的代码,该文件还包含以下内容: 1、对部分重点知识点和难点的提醒和解析 2、在实践中容易遇到的bug及其...

    Android开发教程笔记完全版.rar

    1. **Android系统架构**:Android系统分为Linux内核层、系统库层、应用程序框架层和应用程序层。理解这些层次如何协同工作是学习Android开发的基础。 2. **环境搭建**:首先,你需要安装Android Studio,它是Google...

    菜鸟的Python笔记

    在Python中,模块是包含Python代码的.py文件,可以是程序的一部分也可以是第三方提供的工具。模块可以包含变量、函数、类等等。通过import语句可以引入模块。例如import module,注意在引用模块时不需要加上.py后缀...

    嵌入式系统学习笔记(非常有帮助)

    - **uClinux**:是一种为无MMU(Memory Management Unit,内存管理单元)的处理器设计的嵌入式Linux版本,适用于资源受限的设备。 - **GNU/Linux**:指的是由GNU项目提供的自由软件和Linux内核共同组成的操作系统,...

    新版Android开发教程及笔记-完整版

    新版Android开发教程及笔记将涵盖Android系统的基本架构、应用程序生命周期管理以及UI设计等核心概念。 1. **Android系统架构**:Android系统分为应用层、应用框架层、系统运行库层和Linux内核层。开发者主要在应用...

Global site tag (gtag.js) - Google Analytics