exec函数族,守护进程,线程同步和互斥

时间:2021-07-31 14:55:40

2015.3.2

进程和程序有三点不同:
1,存在位置不同,程序:硬盘,磁盘。进程:内存
2. 程序是静态的,进程是动态的

执行./a.out -->bash->bash程序调用fork()-->子进程将./a.out后面的参数存放到argv[].然后调用exec处理这些参数,最后子进程退出,光标闪动

进程进入停止态:1,调试的时候,2,将前台变成后台运行

线程:每个程序加载到内存后可以对应创建一个或多个顺序执行流(能使进程在同一时刻做不止一件事,每个线程处理各自独立的任务)

回调函数

同步和互斥

exec函数族的基本用法参考:

#include <stdio.h>
#include <string.h>
#include <unistd.h>

void printUsage(const char *argv0)
{
fprintf(stderr,
"Usage : %s <exec type>\n"
"exec type : execl\n"
" execlp,\n"
" execv,\n"
" execvp\n",
argv0);
}

int main(int argc, char *argv[])
{
char *vector[] = {"ps","-f",NULL};

if(argc != 2)
{
printUsage(argv[0]);
return 1;
}

if(0 == strcmp(argv[1],"execl"))
{
if(execl("/bin/ps","ps","-f",NULL) < 0)
{
perror("execl error!");
}
}

else if(0 == strcmp(argv[1],"execlp"))
{
if(execlp("ps","ps","-f",NULL) < 0)
{
perror("execlp error!");
}
}

else if(0 == strcmp(argv[1],"execv"))
{
if(execv("/bin/ps",vector) < 0)
{
perror("execv error!");
}
}

else if(0 == strcmp(argv[1],"execvp"))
{
if(execvp("ps",vector) < 0)
{
perror("execvp error!");
}
}

perror("note the program will not step the exec() function met some errors");

return 0;
}


守护进程的创建和出错处理:(守护进程出错,将错误信息输出到文件中,调用日志函数实现)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcnl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
pid_t pid, sid;
int i,fd;
char *buf = "this is a Daemon\n";

pid = fork();

if(pid < 0)
{
printf("error fork\n");
exit(1);
}

else if(pid > 0)
{
exit(0);
}
openlog("daemon_syslog",LOG_PID,LOD_DAEMON);

if((sid = setsid()) < 0)
{
syslog(LOG_ERR,"%s\n","setsid")
exit(1);
}

if((sid = chdir("/")) < 0)
{
syslog(LOG_ERR,"%s\n","setsid");
exit(1);
}

for(i = 0; i < getdtablesize(); i++)
{
close(i);
}

while(1)
{
if((fd = open("/tmp/daemon.log",O_CREAT|OWRONLY|O_APPEND.0600))<0)
{
syslog(LOG_ERR,"open");
exit(1);
}

write(fd,buf, strlen(buf) + 1);
close(fd);
sleep(10);
}

closelog();
exit(0);
}


线程的创建,结束和回收!

涉及到的相关函数如下:

int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(start_continue)(void *),void *arg);
void pthread_exit(void *retval);
int pthread_join(pthread_t thread, void **thread_result);
int pthread_cancle(pthread_t thread);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

char message[32] = "hello world";
void *thread_function(void *arg);

int main(int argc, char *argv[])
{
pthread_t a_thread;
void *thread_result;

if(pthread_create(&a_thread, NULL, thread_function,(void *)message) < 0)
{
perror("fail to pthread_create");
exit(-1);
}

printf("waiting for thread to finish\n");

if(pthread_join(a_thread, &thread_result) < 0)
{
perror("fail to prhread_join");
exit(-1);
}

printf("message is now %s\n",message);

return 0;
}

void *thread_function(void *arg)
{
printf("thread_function is runing,argument is %s\n",(char *)arg);
strcpy(message,"marked by thread");
pthread_exit("thank you for the cpu time");
}


上面程序编译的时候用这条语句:gcc XXXX.c -lpthread -D _REENTRANT
-lpthread // 链接pthread库
-D _REENTRANT //生成可重入代码

程序运行结果:
lg@lg-desktop:/mnt/hgfs/source test/file IO$ gcc test13.c -lpthread -D_REENTRANT
lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
waiting for thread to finish
thread_function is runing,argument is hello world
message is now marked by thread

 


创建两个线程,分别执行不同的程序,最后退出并由主程序回收。

#include <string.h>
#include <pthread.h>

char message1[] = "AAAAAAAAAA";
char message2[] = "BBBBBBBBBB";
void *thread_function1(void *arg1);
void *thread_function2(void *arg2);


int main(int argc, char *argv[])
{
pthread_t a_thread1,a_thread2;
//void *thread_result;

if(pthread_create(&a_thread1, NULL, thread_function1,(void *)message1) < 0)
{
perror("fail to pthread_create 1");
exit(-1);
}

if(pthread_create(&a_thread2, NULL, thread_function2,(void *)message2) < 0)
{
perror("fail to pthread_create 2");
exit(-1);
}

printf("waiting for thread to finish\n");

if(pthread_join(a_thread1, NULL) < 0)
{
perror("fail to prhread_join");
exit(-1);
}

if(pthread_join(a_thread2,NULL) < 0)
{
perror("fail to prhread_join");
exit(-1);
}

return 0;
}

void *thread_function1(void *arg1)
{
int i;
for(i = 0; i < 3; i++)
{
printf("string is %s \n",(void *)arg1);
sleep(1);
}

pthread_exit("thread 1 is exit");
}


void *thread_function2(void *arg2)
{
int i;
//sleep(10);
for(i = 0; i < 3; i++)
{
printf("string is %s \n",(void *)arg2);
sleep(1);
}

pthread_exit("thread 2 is exit");
}

上面程序的运行结果:
lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
waiting for thread to finish
string is BBBBBBBBBB
string is AAAAAAAAAA
string is BBBBBBBBBB
string is AAAAAAAAAA
string is BBBBBBBBBB
string is AAAAAAAAAA
lg@lg-desktop:/mnt/hgfs/source test/file IO$


线程间同步:
信号量是一个受保护的量,只能通过三种操作进行访问:
1.初始化
2.P操作(申请资源)
3.V操作(释放资源)

信号量的值是非负整数

p操作包含下面内容:

if(信号量 > 0)
{
申请资源的任务继续运行;
信号量的值 - 1;
}
else
{
申请资源的任务阻塞;
}

v操作包含下面的内容:

if(没有任务在等待资源)
{
信号量的值 + 1;
}
else
{
唤醒第一个等待的任务,让其继续运行;
}

同步中涉及到的常用的信号量操作函数如下:

int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_getvalue(sem_t *sem, int svalue);

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

char buf[60];
sem_t sem;
void *function(void * arg);

int main(int argc,char **argv)
{
pthread_t a_thread;
void *thread_result;
if(sem_init(&sem,0,0) < 0)
{
perror("fail to sem_init");
exit(-1);
}

if(pthread_create(&a_thread,NULL,function,NULL) < 0)
{
perror("fail to pthread_create");
exit(-1);
}

printf("input 'quit' to exit\n");

do
{
fgets(buf, 60, stdin);
sem_post(&sem);
}while(strncmp(buf,"quit",4) != 0);

return 0;
}

void *function(void * arg)
{
while(1)
{
sem_wait(&sem);
printf("you enter %d characters\n",strlen(buf)-1);
}
}


进程间互斥:加互斥锁

互斥锁涉及到的一些常用函数如下:

int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

//#define _LOCK_

unsigned int value1, value2,count;
pthread_mutex_t mutex;
void *function(void *arg);

int main(int argc,char ** argv)
{
pthread_t a_thread;

if(pthread_mutex_init(&mutex,NULL) < 0)
{
perror("fail to mutex_init");
exit(-1);
}

if(pthread_create(&a_thread, NULL, function,NULL) < 0)
{
perror("fail to pthread_create");
exit(-1);
}

while(1)
{
count++;
#ifdef _LOCK_

pthread_mutex_lock(&mutex);

#endif

value1 = count;
value2 = count;

#ifdef _LOCK_

pthread_mutex_unlock(&mutex);

#endif
}

return 0;
}

void *function(void *arg)
{
while(1)
{

#ifdef _LOCK_

pthread_mutex_lock(&mutex);

#endif

if(value1 != value2)
{
printf("count = %d, value1 = %d, value2 = %d\n",count, value1, value2);
usleep(100000);
}

#ifdef _LOCK_

pthread_mutex_unlock(&mutex);

#endif
}

return NULL;
}

将define _LOCK_ 屏蔽后运行结果:(不屏蔽程序没有输出,value1和value2相等)
lg@lg-desktop:/mnt/hgfs/source test/file IO$ gcc lock14.c -lpthread -D_REENTRANT
lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
count = 3338702, value1 = 3338702, value2 = 3338701
count = 53692966, value1 = 53692966, value2 = 53692965
count = 89910265, value1 = 89910265, value2 = 89910264
count = 125008213, value1 = 125008213, value2 = 125008212
count = 149351134, value1 = 149351134, value2 = 149351133
count = 171729575, value1 = 171729575, value2 = 171729574
count = 228510044, value1 = 228510044, value2 = 228510043
count = 256495259, value1 = 256495259, value2 = 256495258
count = 287733530, value1 = 287733530, value2 = 287733529
count = 324321776, value1 = 324321776, value2 = 324321775
count = 365523395, value1 = 365523395, value2 = 365523394
count = 420680808, value1 = 420680808, value2 = 420680807
count = 448359597, value1 = 448359597, value2 = 448359596
count = 494800004, value1 = 494800004, value2 = 494800003
count = 528839826, value1 = 528839826, value2 = 528839825
^C
lg@lg-desktop:/mnt/hgfs/source test/file IO$ ^C
lg@lg-desktop:/mnt/hgfs/source test/file IO$

 

互斥锁的另一个参考程序;

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define THREAD_NUM 3
#define REPEAT_NUM 3
#define DELAY_TIME_LEVELS 3.0

pthread_mutex_t mutex;

void *thrd_func(void *arg)
{
int thrd_num = (int)arg;
int delay_time = 0;
int count = 0;
int res;

res = pthread_mutex_lock(&mutex);

if(res)
{

printf("thread %d lock failed\n",thrd_num);
pthread_exit(NULL);
}

printf("thread %d is starting\n",thrd_num);
for(count = 0; count < REPEAT_NUM; count++)
{
delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

sleep(delay_time);
printf("\tThread %d:job %d delay = %d\n",
thrd_num,count, delay_time);
}

printf("thread %d finished\n",thrd_num);
pthread_mutex_unlock(&mutex);

pthread_exit(NULL);
}

int main(void)
{
pthread_t thread[THREAD_NUM];
int no = 0, tpid;
void *thrd_ret;

srand(time(NULL));

pthread_mutex_init(&mutex,NULL);

for(no = 0; no < THREAD_NUM; no++)
{
tpid = pthread_create(&thread[no],NULL,thrd_func,(void *)no);
if(tpid != 0)
{
printf("create thread %d failed\n",no);
exit(-1);
}
}

printf("create treates success\nwaiting for threads to finish...\n");

for(no = 0; no < THREAD_NUM; no++)
{
tpid = pthread_join(thread[no],&thrd_ret);
if(tpid == 0)
{
printf("thread %d joined\n",no);
}
else
{
printf("thread %d join failed\n",no);
}


}
pthread_mutex_destroy(&mutex);

return 0;
}

上面程序运行结果:(结果和书本上有所不同,分析原因是线程执行顺序不同,但是第一个thread 2 is starting有疑问,应该是thread 0 is starting才对,有待解决)
lg@lg-desktop:/mnt/hgfs/source test/file IO$ gcc thread_mutex.c -lpthread -D_REENTRANT
thread_mutex.c: In function ‘thrd_func’:
thread_mutex.c:14: warning: cast from pointer to integer of different size
thread_mutex.c: In function ‘main’:
thread_mutex.c:58: warning: cast to pointer from integer of different size
lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
create treates success
waiting for threads to finish...
thread 2 is starting
Thread 2:job 0 delay = 3
Thread 2:job 1 delay = 3
Thread 2:job 2 delay = 1
thread 2 finished
thread 1 is starting
Thread 1:job 0 delay = 1
Thread 1:job 1 delay = 1
Thread 1:job 2 delay = 1
thread 1 finished
thread 0 is starting
Thread 0:job 0 delay = 3
Thread 0:job 1 delay = 3
Thread 0:job 2 delay = 2
thread 0 finished
thread 0 joined
thread 1 joined
thread 2 joined
lg@lg-desktop:/mnt/hgfs/source test/file IO$

***************************************************************************************************************************************************************
***************************************************************************************************************************************************************
***************************************************************************************************************************************************************
***************************************************************************************************************************************************************