c编程相关(学习笔记)

from:《linux操作系统下c语言编程入门》及相关网上资料

A:基础知识

1.常用编译:gcc -o hello hello.c
-o表示输出可执行文件名
-c表示只要求编译器输出目标代码,而不是可执行文件
-g表示在编译的时候要求编译器提供以后对程序进行调试的信息

###注意有printf()这类函数时要加上#include<stdio.h>,否则有警告。

2.Makefile
格式:
target:components
TAB rule(TAB就是一个tab键,即需要空一个tab,否则出现错误)

简化:(三个常用变量:$@,$^,$<)
$@(目标文件),$^(所有的依赖文件),$<(第一个依赖文件)


如此可以将以下Makefile
main:main.o mytool1.o mytool2.o
    gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
    gcc -c main.c
mytool1.o:mytool1.c mytool1.h
    gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
    gcc -c mytool2.c

改为如下形式:
main:main.o mytool1.o mytool2.o
    gcc -o $@ $^(#####注意这这中间有一个空格)
main.o:main.c mytool1.h mytool2.h
    gcc -c $<
mytool1.o:mytool1.c mytool1.h
    gcc -c $<
mytool2.o:mytool2.c mytool2.h
    gcc -c $<

还可以简化为:
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
..c.o:
gcc -c $<
这个规则表示所有的.o文件都是依赖于相应的.c文件安的。

3.程序库的链接
#include<stdio.h>
#include<math.h>
int main()
{
        double value=100.0;
        printf("Value: %f\n",sqrt(value));
        return 0;
}

当用gcc -o temp temp.c进行编译时,会出现错误(提示undefined reference to `sqrt')
需要用如下方式:gcc -o temp temp.c -lm(lm表示链接到数学库)

有的时候需要用-L进行手动指定库文件。


4.程序的调试(不知道额)
这个讲得不错
http://blog.csdn.net/herostarone/article/details/7326722

(1)gcc -g -Wall -o temp temp.c(-Wall是表示输出所有警告)
(2)启动Gdb:gdb temp(可以看到载入信息)
(3)查看源文件:(gdb) l
(4)设置断点:(gdb) b 行号
(5)删除断点:(gdb) delete 第几个断点
(6)查看断点信息:(gdb) info b
(7)运行代码:(gdb) r
(8)查看变量值:(gdb) p 变量名(p代表print)
(9)单步执行:(gdb) n
(10)恢复程序执行:(gdb) c(c代表continuing)

B:进程介绍

1.进程的概念
2.进程的身份
3.进程的创建
4.守护进程的创建

1.进程的概念
通俗的讲,程序是一个包含可执行代码的文件,是一个静态的文件。
而进程是一个开始执行但是还没有结束的程序的实例。

进程的五个状态:新建/运行/阻塞/就绪/完成


2.获得进程的标志(ID)

getpid()——》进程的ID
getppid()——》父进程的ID
进程为程序服务,程序为用户服务

getuid():获得进程的所有者的ID
geteuid():有效用户ID
getgid():组ID
getegid():有效组ID

getpwuid():用户的其他信息(登录名等)

头文件:<sys/types.h>(基本系统数据类型),是Unix/Linux系统的基本系统数据类型的头文件,含有size_t,time_t,pid_t等类型。

头文件:<unistd.h>(是POSIX标准定义的unix类系统定义符号常量的头文件,包含:read,write,getpid等函数,类似于windows下的<windows.h>

头文件:<pwd.h>定义了结构体:struct passwd

struct passwd{
    char *pw_name;   登录名
    char *pw_passwd;    登录口令
    uid_t pw_uid;    用户ID
    gid_t pw_gid;    用户组ID
    char *pw_gecos;    用户的真名
    char *pw_dir    用户的目录
    char *pw_shell;    用户的shell
};

具体实现时还有问题,需要后续解决;

3.进程的创建

调用fork()即可

系统调用:wait()使父进程阻塞直到一个子进程结束或父进程接受到一个信号。
成功时返回子进程的ID,否则返回-1。


waitpid()等待指定的子进程直到子进程返回

while(((child=wait(&status))==-1)&(errno==EINTR);
//一直等到子进程结束,errno==EINTR表示函数调用被信号处理函数中断。

4.守护进程的创建

什么是“守护进程“?
守护进程(Daemon)指在UNIX或其他多任务操作系统中在后台执行的电脑程序,不受用户的直接操控。
一般没有任何父进程(PPID=1),直接位于init之下

成为守护进程的方法:对一个子进程调用fork,然后使其父进程立即终止,使得这个子进程能在init下运行。这种方法通常称为“脱壳”

DOS下 称为驻留程序(TSR)(常驻内存程序)。
windows下称为windows服务的应用程序

实例是一个后台检查邮件的程序,在每一个指定的时间去检查邮箱,如果有邮件则用喇叭报警。

后台进程的创建思想:父进程创建一个子进程,子进程杀死父进程,信号处理的工作由子进程处理。

//此为守护进程的实例
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>//返回数据的结构体
#include<stdio.h>
#include<errno.h>
#include<fcntl.h>//定义fcntl()和open()函数的需求和参数
#include<signal.h>

//Linux的默认个人邮箱地址是/var/spool/mail/用户的登录名

#define MAIL "/var/spool/mail/zn"

//睡眠10s
#define SLEEP_TIME 10

int main()
{
        pid_t child;
        if((child=fork())==-1)
        {
        printf("Fork error:%s\n",strerror(errno));
        exit(1);
        }

        else if(child>0)
        {
        while(1)
        {
        if(kill(getppid(),SIGTERM)==-1)
        {
        printf("Kill parent Error:%s\n",strerror(errno));
        exit(1);
        }
        }
        }

        {
    int mailfd;
        while(1)
        {
        if((mailfd=open(MAIL,O_RDONLY))!=-1)
        {
        printf("有邮件,请查收!\n");
        fprintf(stderr,"%s","\007");
        close(mailfd);
        }
        sleep(SLEEP_TIME);
        }
        }

}

posted on 2015-01-26 11:01  weekman  阅读(278)  评论(0编辑  收藏  举报