Linux环境编程之进程(三):函数间跳转

引言:在编写程序时,经常在函数内部使用goto语句来跳转,从而进行出错处理,那么如果想要在函数之间进行跳转该怎么做呢?使用setjmp和longjmp函数。

给出示例程序:

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

static void f1(int, int, int, int);
static void f2(void);

static jmp_buf 	jmpbuffer;
static int 		globval;

int
main(void)
{
	int 	autoval;
	register int regival;
	volatile int volaval;
	static 	int  statval;

	globval = 1;
	autoval = 2;
	regival = 3;
	volaval = 4;
	statval = 5;

	if(setjmp(jmpbuffer) != 0){
		printf("after longjmp:\n");
		printf("global = %d, autoval = %d, regival  = %d, volaval = %d, statval = %d\n",
						globval, autoval, regival, volaval, statval);
		exit(0);
	}
	/*
	 * Change variable after setjmp, buf before longjmp.
	 */
	globval = 95;
	autoval = 96;
	regival = 97;
	volaval = 98;
	statval = 99;

	f1(autoval, regival, volaval, statval);/*never returns*/
	exit(0);
}

static void
f1(int i, int j, int k, int l)
{
	printf("in f1():\n");
	printf("global = %d, autoval = %d, regival  = %d, volaval = %d, statval = %d\n",
						globval,i, j, k, l);
	f2();
}
static void
f2(void)
{
	longjmp(jmpbuffer, 1);
}

编译程序测试结果:

in f1():
global = 95, autoval = 96, regival  = 97, volaval = 98, statval = 99
after longjmp:
global = 95, autoval = 96, regival  = 97, volaval = 98, statval = 99

Linux环境编程之进程(三):函数间跳转

时间: 2024-08-25 15:02:23

Linux环境编程之进程(三):函数间跳转的相关文章

Linux环境编程之信号(三):一些信号函数

(一)kill和raise函数 kill函数将信号发送给进程或进程组.raise函数则允许进程自身发送信号. #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); int raise(int  signo);  //返回值:若成功则返回0,若出错则返回-1. 参数:pid参数有4种情况:1.pid > 0 将信号发送给进程为pid的进程.2.pid == 0 将该信号发送给与发送进程属

Linux环境编程之进程(五):竞争条件以及exec函数

(一) 当多个进程企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序时,就认为它们发生了竞争关系.避免竞争的条件,给出apue上的一个代码吧: #include "apue.h" static void charatatime(char *); int main(void) { pid_t pid; TELL_WAIT(); /*set things up for TELL_XXX & WAIT_XXX*/ if((pid == fork()) < 0){ e

Linux环境编程之同步(三):读写锁

概述 互斥锁把试图进入我们称之为临界区的所有其他线程都阻塞住.该临界区通常涉及对由这些线程共享一个或多个数据的访问或更新.读写锁在获取读写锁用于读某个数据和获取读写锁用于写直接作区别.读写锁的分配规则如下: 1.只要没有线程持有某个给定的读写锁用于写,那么任意数目的线程可以持有该读写锁用于读. 2.仅当没有线程持有某个给定的读写锁用于读或用于写时,才能分配该读写锁用于写. 即只要没有线程在修改某个给定的数据,那么任意数目的线程都可以拥有该数据的读访问权.仅当没有其他线程在读或修改某个给定的数据时

Linux环境编程之进程(一):main函数调用、进程终止以及命令行参数和环境表

(一)main函数调用 main函数作为程序运行时的入口函数,它是如何被调用的呢?首先必须清楚一点,main函数也是一个函数,它只有被调用才能够执行.其实,在执行可执行程序时,在调用main函数之前,内核会先调用一个特殊的启动例程,将此启动例程作为可执行程序的起始地址.启动例程是如何作为可执行程序的起始地址的?这是由链接编译器设置的,而链接编译器则是由C编译器(如gcc编译器)调用的.启动例程作为可执行程序的起始地址主要做哪些工作呢?启动例程从内核取得命令行参数和环境变量值,以此来为main函数

Linux环境编程之进程(二):程序的存储空间布局

引言: 一个写好的程序一般要存放在存储器中,那么程序中的代码.数据等各部分,是如何有规律的存放在存储器中的呢? (一) 一个存储的程序可分为五部分:正文段.初始化数据段.非初始化数据段.栈.堆.其典型的存储安排如下图: 正文段:这是由CPU执行的机器指令的部分.通常,正文段是可共享的,所以即使是频繁执行的程序在存储器中也只需要一个副本,另外正文段常常是只读的,以防止程序由于意外而修改其自身的指令. 初始化数据段:通常称为数据段,它包含了程序中需要明确地赋初值的变量. 非初始化数据段:通常称为bs

Linux环境编程之进程(七):守护进程

守护进程也是一种进程,它由如下特性: 1.生存期较长,在系统自举时启动,仅在系统关闭时终止. 2.没有控制终端,在后台运行. 系统中有很多守护进程,它们执行日常事务活动.如日志进程syslogd.web服务器httpd.邮件服务器sendmail和数据块服务器mysqld等.大多数守护进程都是以超级用户(用户ID为0)特权运行.没有一个守护进程具有控制终端,其终端设置为问号(?),终端前台进程组ID设置为-1.内核守护进程以无控制终端方式启动.用户层守护进程缺少控制终端可能是守护进程调用了set

Linux环境编程之进程(四):创建新进程、执行程序和进程终止

引言: 对于每个进程,都有一个非负整数表示的唯一进程ID.虽然进程的ID是唯一的,但却是可重用的.系统中有一些专用的进程.如ID为0的进程通常是调度进程,也成交换进程或系统进程(它是内核进程).进程ID为1通常是init进程,它是一个普通的用户进程.一些与进程ID有关的函数: #include <unistd.h> pid_t getpid(void);   //返回值:调用进程的进程ID pit_t getppid(void); //返回值:调用进程的父进程ID uid_t getuid(v

Linux环境编程之进程(六):进程组

进程组 每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或多个进程的集合.每个进程组有一个唯一的进程组ID.进程组ID类似于进程ID--它是一个整数,并可存放在pid_t数据类型中.函数getpgrp返回调用进程的进程组ID. 每个进程组都可以有一个组长进程.组长进程的标识是,其进程组ID等于其进程ID.组长进程可以创建一个进程组,创建该组中的进程,然后终止.只要在某个进程组中有一个进程存在,则进程组就存在,这与其组长进程是否终止无关.从进程组创建开始到其中最后一个进程离开为止的时

LINUX环境编程之进程控制(上)

一.进程标识 每个进程都有一个非负整型表示的唯一进程ID.虽然该id是唯一的,但是进程ID是可复用的.当一个进程终止后,其进程id就成为复用的候选者. 系统中有一些专用进程,但是具体细节随实现而不同.ID为0的进程通常是调度进程,常常被称为交换进程.该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被成为系统进程.进程ID 1通常是init进程,在自举过程结束时有内核调用.init进程绝不会终止,他是一个普通用户的用户进程(与交换进程不同,他不是内核中的系统进程),但是它以超级用户权限运行