A global function is a VI whose principal job is to store some data (typically in the shift registers of a WHILE loop with LOOP set to false).
At one time (LabView 2 and earlier) there were no global variables. The way you stored something for use by two or more independent VIs was to have a VI with a READ/WRITE switch input, a DATA input and a DATA output. If you called it with WRITE = TRUE, it stored the data you gave it. If you called it with WRITE = FALSE, you read out the data it had stored. Advantages: 1... You don't make copies of the data when you read it. That's important for memory usage when the data is a 200x64*512 array of CDB (I've used it like that). 2... It's atomic. If you want to store 6 separate items into six globals, you have the problem of knowing when ALL items have changed. Whatever reads them might read them during your change, and read 3 old values and 3 new ones. The global function is guaranteed to deliver the data as a set. 3... You can add functionality. I like to encapsulate things - for example: a config file handler. I like to have a handler (global function) for each type of config file. It has a FUNCTION input, which typically has functions like INIT, SET DEFAULT, READ FILE, WRITE FILE, COMPARE, and so on. The actual config is stored by this VI (in a shift reg, natch). Anybody who wants to deal with a config file calls this VI. That way, anytime I need to change something involving a config file, I have ONE and ONLY ONE place to go. In my multi-window project, I used a global function to create, store, and manage the occurrences.